diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2ce3afa911471..24bd06a8f263e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,25 +13,13 @@ name: Build on: - pull_request: - paths-ignore: - - 'Documentation/**' - - 'tools/ci/docker/linux/**' push: - paths-ignore: - - 'Documentation/**' - branches: - - master - - 'releases/*' - tags: + branches: [master] + pull_request: permissions: contents: read -concurrency: - group: build-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - jobs: Fetch-Source: runs-on: ubuntu-latest @@ -67,13 +55,13 @@ jobs: # Determine the repo and leave that unset to use the normal checkout behavior # of using the merge commit instead of HEAD case $GITHUB_REPOSITORY in - "apache/nuttx") + "tiiuae/nuttx") # OS echo "Triggered by change in OS" APPS_REF=$REF_NAME ;; - "apache/nuttx-apps" ) + "tiiuae/incubator-nuttx-apps" ) # APPS OS_REF=$REF_NAME echo "Triggered by change in APPS" @@ -91,7 +79,7 @@ jobs: - name: Checkout nuttx repo uses: actions/checkout@v4 with: - repository: apache/nuttx + repository: tiiuae/nuttx ref: ${{ steps.gittargets.outputs.os_ref }} path: sources/nuttx fetch-depth: 1 @@ -101,7 +89,7 @@ jobs: - name: Checkout apps repo uses: actions/checkout@v4 with: - repository: apache/nuttx-apps + repository: tiiuae/incubator-nuttx-apps ref: ${{ steps.gittargets.outputs.apps_ref }} path: sources/apps fetch-depth: 1 @@ -115,71 +103,13 @@ jobs: name: source-bundle path: sources.tar.gz - Linux: - needs: Fetch-Source + Build: runs-on: ubuntu-latest - env: - DOCKER_BUILDKIT: 1 - - strategy: - matrix: - boards: [arm-01, arm-02, arm-03, arm-04, arm-05, arm-06, arm-07, arm-08, arm-09, arm-10, arm-11, arm-12, arm-13, other, risc-v, sim-01, sim-02, xtensa, codechecker] - - steps: - - name: Download Source Artifact - uses: actions/download-artifact@v3 - with: - name: source-bundle - path: . - - - name: Extract sources - run: tar zxf sources.tar.gz - - - name: Docker Login - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Docker Pull - run: docker pull ghcr.io/apache/nuttx/apache-nuttx-ci-linux - - - name: Export NuttX Repo SHA - run: echo "nuttx_sha=`git -C sources/nuttx rev-parse HEAD`" >> $GITHUB_ENV - - - name: Run builds - uses: ./sources/nuttx/.github/actions/ci-container - env: - BLOBDIR: /tools/blobs - with: - run: | - echo "::add-matcher::sources/nuttx/.github/gcc.json" - export ARTIFACTDIR=`pwd`/buildartifacts - git config --global --add safe.directory /github/workspace/sources/nuttx - git config --global --add safe.directory /github/workspace/sources/apps - cd sources/nuttx/tools/ci - if [ "X${{matrix.boards}}" = "Xcodechecker" ]; then - ./cibuild.sh -c -A -R --codechecker testlist/${{matrix.boards}}.dat - else - ./cibuild.sh -c -A -R testlist/${{matrix.boards}}.dat - fi - - - uses: actions/upload-artifact@v3 - if: ${{ always() }} - with: - name: linux-builds - path: buildartifacts/ - continue-on-error: true - - macOS: - permissions: - contents: none - runs-on: macos-13 needs: Fetch-Source strategy: + fail-fast: false matrix: - boards: [macos, sim-01, sim-02] + boards: [ssrc-arm, ssrc-riscv] steps: - name: Download Source Artifact uses: actions/download-artifact@v3 @@ -190,32 +120,11 @@ jobs: - name: Extract sources run: tar zxf sources.tar.gz - - name: Restore Tools Cache - id: cache-tools - uses: actions/cache@v3 - env: - cache-name: ${{ runner.os }}-cache-tools - with: - path: ./sources/tools - key: ${{ runner.os }}-tools-${{ hashFiles('./sources/nuttx/tools/ci/cibuild.sh') }} - - - name: Export NuttX Repo SHA - run: echo "nuttx_sha=`git -C sources/nuttx rev-parse HEAD`" >> $GITHUB_ENV - - # Released version of Cython has issues with Python 11. Set runner to use Python 3.10 - # https://github.com/cython/cython/issues/4500 - - uses: actions/setup-python@v5 - with: - python-version: '3.10' - - name: Run Builds + # cibuild.sh -i installs the tools for us + - name: Run builds run: | echo "::add-matcher::sources/nuttx/.github/gcc.json" export ARTIFACTDIR=`pwd`/buildartifacts cd sources/nuttx/tools/ci ./cibuild.sh -i -c -A -R testlist/${{matrix.boards}}.dat - - uses: actions/upload-artifact@v3 - with: - name: macos-builds - path: buildartifacts/ - continue-on-error: true diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 6032d1960bc08..ca0cd858f63b8 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -32,7 +32,7 @@ jobs: - name: Checkout nuttx repo uses: actions/checkout@v4 with: - repository: apache/nuttx + repository: tiiuae/nuttx path: nuttx fetch-depth: 0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000000..abcd35cf08c12 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,72 @@ +name: "CodeQL" + +on: + push: + branches: [master] + pull_request: + branches: [master] + workflow_dispatch: + +jobs: + analyze: + name: Analyze (${{ matrix.language }}/${{ matrix.config}}) + runs-on: 'ubuntu-latest' + timeout-minutes: 60 + permissions: + # required for all workflows + security-events: write + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: c-cpp + build-mode: manual + config: icicle:nsh + - language: c-cpp + build-mode: manual + config: imx93-evk:nsh + - language: python + build-mode: none + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Checkout apps + uses: actions/checkout@v4 + with: + repository: 'tiiuae/incubator-nuttx-apps.git' + path: 'apps' + ref: 'master' + - name: Install tools + run: | + mv apps ../apps + sudo apt-get install kconfig-frontends + mkdir -p ../bin + cd ../bin + wget https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz + wget https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-elf.tar.xz + tar xvf riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz + tar xvf arm-gnu-toolchain-13.2.rel1-x86_64-aarch64-none-elf.tar.xz + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + + - if: matrix.build-mode == 'manual' + run: | + export PATH=$PATH:$PWD/../bin/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/ + export PATH=$PATH:$PWD/../bin/arm-gnu-toolchain-13.2.Rel1-x86_64-aarch64-none-elf/bin + ./tools/configure.sh ${{matrix.config}} + make + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/Documentation/ReleaseNotes/NuttX-12.4.0 b/Documentation/ReleaseNotes/NuttX-12.4.0 new file mode 100644 index 0000000000000..6a2c70734e406 --- /dev/null +++ b/Documentation/ReleaseNotes/NuttX-12.4.0 @@ -0,0 +1,519 @@ +NuttX-12.4.0 +------------ + +What's New In This Release +Improvements to Core OS +sched +* [#10919](https://github.com/apache/nuttx/pull/10919) sched: assert: move the backtrace dump after the stack dump +* [#11195](https://github.com/apache/nuttx/pull/11195) sched: assert: restore assertion registers to array of last registers +* [#10858](https://github.com/apache/nuttx/pull/10858) sched: assert.c: Print process name in assert dump +* [#11131](https://github.com/apache/nuttx/pull/11131) sched: Check for zero sleep time and yield CPU +* [#11226](https://github.com/apache/nuttx/pull/11226) sched: delete check when pick nexttcb in readytorun list +* [#11038](https://github.com/apache/nuttx/pull/11038) sched: env_dup: fix issue about USE_AFTER_FREE +* [#11102](https://github.com/apache/nuttx/pull/11102) sched: explicitly select the cpuload clock source configuration +* [#10816](https://github.com/apache/nuttx/pull/10816) sched: Fix dependencies of CONFIG_SCHED_CPULOAD_ settings +* [#11036](https://github.com/apache/nuttx/pull/11036) sched: Follow o_cloexe semantics when calling the exec function +* [#10867](https://github.com/apache/nuttx/pull/10867) sched: format: modify spin_lock_irqsave format +* [#11018](https://github.com/apache/nuttx/pull/11018) sched: group/killchildren: replace syscall(2) to kernel api +* [#10605](https://github.com/apache/nuttx/pull/10605) sched: Implement ticket spinlock +* [#10827](https://github.com/apache/nuttx/pull/10827) sched: Improve adjtime() functionality +* [#11231](https://github.com/apache/nuttx/pull/11231) sched: lock refine: remove sched_[un]lock in xxx_waitsample +* [#11302](https://github.com/apache/nuttx/pull/11302) sched: misc/rwlock:Implementing read/write locks. +* [#11347](https://github.com/apache/nuttx/pull/11347) sched: Print more information in assert +* [#11017](https://github.com/apache/nuttx/pull/11017) sched: pthread/barrierwait: replace syscall(2) to kernel api +* [#10929](https://github.com/apache/nuttx/pull/10929) sched: Remove the unused tcb argument from group_setupidlefiles +* [#10776](https://github.com/apache/nuttx/pull/10776) sched: rw spinlock +* [#11124](https://github.com/apache/nuttx/pull/11124) sched: rw spinlocks: cosmetic changes +* [#11191](https://github.com/apache/nuttx/pull/11191) sched: sem_holder.c: When accessing SEM_WAITLIST, use holder's addrenv +* [#11257](https://github.com/apache/nuttx/pull/11257) sched: semaphore: Move POSIX regulated parts of semaphores into libc +* [#11252](https://github.com/apache/nuttx/pull/11252) sched: sigaction: Expand si_user for non-kernel signals +* [#10970](https://github.com/apache/nuttx/pull/10970) sched: smp call exit immediately when cpuset change to 0. +* [#10861](https://github.com/apache/nuttx/pull/10861) sched: spinlock: Add spin_lock_init and spin_is_locked macro +* [#11348](https://github.com/apache/nuttx/pull/11348) sched: Stack recored:Add maximum stack statistics when the task is running +* [#9163](https://github.com/apache/nuttx/pull/9163) sched: Stop the sched timer when possible to save the power in tickless mode +* [#10934](https://github.com/apache/nuttx/pull/10934) sched: support smp function call +* [#11032](https://github.com/apache/nuttx/pull/11032) sched: task: [posix]spawn: Simplify how spawn attributes are handled +* [#11241](https://github.com/apache/nuttx/pull/11241) sched: task: pthread_cancelpt: Fix nxtask_delete from another task group +* [#11165](https://github.com/apache/nuttx/pull/11165) sched: task: pthread_cancelpt: Move cancel point handling to libc, data to TLS +* [#11097](https://github.com/apache/nuttx/pull/11097) sched: task: Remove spawn_proxyattrs as obsolete implementation +* [#11177](https://github.com/apache/nuttx/pull/11177) sched: taskfiles: skip unnecessary file open/close operations to improve performance +* [#11250](https://github.com/apache/nuttx/pull/11250) sched: taskspawn: fix spawn fail if enable FDCHECK +* [#10834](https://github.com/apache/nuttx/pull/10834) sched: timer: handle perf count overflow + +mm +* [#11068](https://github.com/apache/nuttx/pull/11068) mm: both use spin_lock_irqxx() when operated delaylist +* [#11183](https://github.com/apache/nuttx/pull/11183) mm: free delay list when exceeding specified count +* [#11258](https://github.com/apache/nuttx/pull/11258) mm: kmap: Finalize kmap implementation for RISC-V +* [#10837](https://github.com/apache/nuttx/pull/10837) mm: kmap: Fix bug in kmm_unmap +* [#10876](https://github.com/apache/nuttx/pull/10876) mm: kmap: Fix several issues with the kmm_map interface +* [#11114](https://github.com/apache/nuttx/pull/11114) mm: kmap: Fix bad dependency to ARCH_VMA_MAPPING +* [#11092](https://github.com/apache/nuttx/pull/11092) mm: improve SMP performance +* [#11152](https://github.com/apache/nuttx/pull/11152) mm: record the maximum system memory usage +* [#11168](https://github.com/apache/nuttx/pull/11168) mm: Remove mm_spinlock +* [#10984](https://github.com/apache/nuttx/pull/10984) mm: Replace enter_critical_section with spin_irqsave + +libs +* [#11408](https://github.com/apache/nuttx/pull/11408) libc: add fgetwc, getwc, ungetwc wchar api implementation +* [#10602](https://github.com/apache/nuttx/pull/10602) libc: add support for custom streams with fopencookie() +* [#11011](https://github.com/apache/nuttx/pull/11011) libc: add support for memory buffer stream with fmemopen() +* [#11274](https://github.com/apache/nuttx/pull/11274) libc: add support for open_memstream +* [#11288](https://github.com/apache/nuttx/pull/11288) libc: arm: add support of PACBTI +* [#10969](https://github.com/apache/nuttx/pull/10969) libc: Change errno to set_errno and get_errno +* [#11294](https://github.com/apache/nuttx/pull/11294) libc: Fix -nan issue with f32 +* [#11198](https://github.com/apache/nuttx/pull/11198) libc: Fix improper handling of 64 bit types for libvsprintf +* [#11322](https://github.com/apache/nuttx/pull/11322) libc: Handle PCREL_HI20/LO12_I/S relocations correctly +* [#10994](https://github.com/apache/nuttx/pull/10994) libc: Improve stdio unlock version function +* [#11364](https://github.com/apache/nuttx/pull/11364) libc: lib_slcd: fix encode/decode of binary nibble to/from ascii hex +* [#11035](https://github.com/apache/nuttx/pull/11035) libc: localtime: fix the timezone error caused by minor error +* [#11281](https://github.com/apache/nuttx/pull/11281) libc: machine/arm: align related implementations of armv7 architecture +* [#10927](https://github.com/apache/nuttx/pull/10927) libc: machine: Remove FAR from sparc +* [#11133](https://github.com/apache/nuttx/pull/11133) libc: realpath: allocate link buffer of pseudofs to save stack +* [#10913](https://github.com/apache/nuttx/pull/10913) libc: Refine the implementation of fopen/fdopen +* [#10993](https://github.com/apache/nuttx/pull/10993) libc: Remove the unused lib_libdtoa.c +* [#11137](https://github.com/apache/nuttx/pull/11137) libc: Solve some problems encountered during cmake compilation +* [#10992](https://github.com/apache/nuttx/pull/10992) libc: stdio: Change FILE buffer field from "unsigned char *" to "char *" +* [#11063](https://github.com/apache/nuttx/pull/11063) libc: stdlib/lib_exit.c: fix multiple definition of __dso_handle and sethost.sh: add MSYS environmen for msys2 +* [#11447](https://github.com/apache/nuttx/pull/11447) libc: stream: add stream interface +* [#11350](https://github.com/apache/nuttx/pull/11350) libc: Support gdbstub kernal debugging +* [#11346](https://github.com/apache/nuttx/pull/11346) libc: Supports storing coredump into block devices +* [#10862](https://github.com/apache/nuttx/pull/10862) libc: memfd: shm_unlink or unlink anonymous file +* [#10891](https://github.com/apache/nuttx/pull/10891) libc: memfd: turn a runtime error into a linker error +* [#10972](https://github.com/apache/nuttx/pull/10972) libds: add missing observer_b16.c to cmake build +* [#10915](https://github.com/apache/nuttx/pull/10915) libdsp: lib_observer.c: use float numbers for some calculations +* [#10979](https://github.com/apache/nuttx/pull/10979) libdsp: update LP_FILTER comment +* [#11256](https://github.com/apache/nuttx/pull/11256) libm: Fix an issue that public header files are not exported +* [#11162](https://github.com/apache/nuttx/pull/11162) libm: newlib: Change the download site to https +* [#11386](https://github.com/apache/nuttx/pull/11386) libs: log2ceil: Move implementation of log2ceil to a common place +* [#11043](https://github.com/apache/nuttx/pull/11043) libs: modlib: optimize code and add arch api for allocating data section +* [#11394](https://github.com/apache/nuttx/pull/11394) libxx: cmake: remove useless code +* [#11050](https://github.com/apache/nuttx/pull/11050) libxx: Silence warnings when building libcxx. +* [#11301](https://github.com/apache/nuttx/pull/11301) libxx: upgrade llvm version to 17.0.6 +* [#10860](https://github.com/apache/nuttx/pull/10860) libxx: Use gnu++20 option only if using libcxx +misc +* [#11242](https://github.com/apache/nuttx/pull/11242) Revert "libc/lib_bzero:Add bzero prototype." +* [#10881](https://github.com/apache/nuttx/pull/10881) arm, arm64, xtensa, libxx: Change sed -r to sed -E to support macOS +* [#11027](https://github.com/apache/nuttx/pull/11027) assert: rename __ASSERT to __ASSERT__ to avoid conflict +* [#11025](https://github.com/apache/nuttx/pull/11025) audio: add amr format support +* [#11055](https://github.com/apache/nuttx/pull/11055) binfmt/elf: Select ARCH_USE_TEXT_HEAP if ARCH_HAVE_TEXT_HEAP +* [#11238](https://github.com/apache/nuttx/pull/11238) clock.h: use CONFIG_DEBUG_SCHED to test init ticks +* [#10924](https://github.com/apache/nuttx/pull/10924) crypto/rsa_verify: export rsa verify via /dev/crypto +* [#10978](https://github.com/apache/nuttx/pull/10978) debug/assert: decouple configuration of show file name feature +* [#10809](https://github.com/apache/nuttx/pull/10809) dma: support source/destination address auto step +* [#10870](https://github.com/apache/nuttx/pull/10870) fixedmath: add abs and sign operations +* [#11111](https://github.com/apache/nuttx/pull/11111) ioctl: add definitions related to ethtool +* [#11121](https://github.com/apache/nuttx/pull/11121) ioctl: add SIOCGIWNAME support +* [#11026](https://github.com/apache/nuttx/pull/11026) kernel: replace all sem_* to nxsem_*: in kernel space +* [#10849](https://github.com/apache/nuttx/pull/10849) langinfo: The character U+ff0c "," could be confused with the ASCII character U… +* [#11243](https://github.com/apache/nuttx/pull/11243) list: search prev item in reverse order +* [#11221](https://github.com/apache/nuttx/pull/11221) poll: pollsetup should notify only one fd passed by caller +* [#10892](https://github.com/apache/nuttx/pull/10892) refine: move BIT Macro to nuttx/bits.h +* [#11218](https://github.com/apache/nuttx/pull/11218) spinlock: Move the inclusion of stdatomic.h to source file +* [#10869](https://github.com/apache/nuttx/pull/10869) sys/types: supporting 32-bit IDs for gid_t/uid_t +* [#11207](https://github.com/apache/nuttx/pull/11207) tcbinfo:remove total_num form tcbinfo. +* [#11298](https://github.com/apache/nuttx/pull/11298) video: Update v4l2m2m interface & create videoio.h +* [#11362](https://github.com/apache/nuttx/pull/11362) virtio.h: add virtio_has_feature api for virtio driver +Build System +Improvements +* [#11007](https://github.com/apache/nuttx/pull/11007) Revert "make/archive: Use the full path name when matching or storing… +* [#11047](https://github.com/apache/nuttx/pull/11047) applications: Move the test tools in the system to the testing +* [#11395](https://github.com/apache/nuttx/pull/11395) cmake: build file support with libcxx 17.0.6 +* [#10982](https://github.com/apache/nuttx/pull/10982) cmake: correct cmake rule file name +* [#11375](https://github.com/apache/nuttx/pull/11375) cmake: fix NUTTX_COMMON_DIR +* [#11031](https://github.com/apache/nuttx/pull/11031) cmake: init RISC-V cmake qemu-rv build +* [#10843](https://github.com/apache/nuttx/pull/10843) cmake: raise error if previous make build was not cleaned +* [#10879](https://github.com/apache/nuttx/pull/10879) fix: TreeNode has same attribute with NodeMixin +* [#10968](https://github.com/apache/nuttx/pull/10968) nuttx: generate nuttx.map file when enable debug link map. +* [#11303](https://github.com/apache/nuttx/pull/11303) sh: Enhanced compilation system +* [#11432](https://github.com/apache/nuttx/pull/11432) tools: config.mk: whether verbosity is enabled or not, should use bash +* [#11098](https://github.com/apache/nuttx/pull/11098) tools: configure.c and tools/sethost.sh Add CONFIG_EXPERIMENTAL for configure windows native +Architectural Support +New Architecture Support +* [#11319](https://github.com/apache/nuttx/pull/11319) arm:imxrt: Add support for imxrt1170 Soc and imxrt1170-evk board +* [#11371](https://github.com/apache/nuttx/pull/11371) riscv: Add support for Bouffalo Lab BL808 SoC (T-Head C906) + +Architecture Improvements +* [#10836](https://github.com/apache/nuttx/pull/10836) arch: add a flag indicating that the chip doesn't support DMA transfer from/to FLASH +* [#10759](https://github.com/apache/nuttx/pull/10759) arch: add use_data to g_tcbinfo +* [#11190](https://github.com/apache/nuttx/pull/11190) arch: dumponexit: unify dump on exit to common code +* [#10828](https://github.com/apache/nuttx/pull/10828) arch: simplify ARCH_PERF_EVENTS related code +* [#11160](https://github.com/apache/nuttx/pull/11160) arch: textheap: add _heapmember declare for text and data heap +arm + * [#11282](https://github.com/apache/nuttx/pull/11282) clang: replace deprecated parameter +* [#11170](https://github.com/apache/nuttx/pull/11170) Let's old arm's arm_doirq return register context like armv7-a +* [#11413](https://github.com/apache/nuttx/pull/11413) debug:fix gdbstub clear fpb & dwt when already use jtag/swo bug +* [#11166](https://github.com/apache/nuttx/pull/11166) armv8-m: Fix typo error for NVIC_SYSHCON_HARDFAULTPENDED + +* [#11118](https://github.com/apache/nuttx/pull/11118) cxd56xx: Support to get gnss firmware version + +* [#11398](https://github.com/apache/nuttx/pull/11398) imxrt: Extend FlexIO support to 117x +* [#11436](https://github.com/apache/nuttx/pull/11436) imxrt: flexio move ifdef guard lower +* [#11012](https://github.com/apache/nuttx/pull/11012) imxrt: NXP I2C non-DMA end only on stop with end of packet +* [#11000](https://github.com/apache/nuttx/pull/11000) imxrt: nxp lpi2c calculated timeout can not be 0 +* [#11033](https://github.com/apache/nuttx/pull/11033) imxrt: NXP lpi2c DMA transaction only need the status conditioned +* [#11164](https://github.com/apache/nuttx/pull/11164) imxrt: NXP Serial Do not wait on TXDMA semaphore +* [#11070](https://github.com/apache/nuttx/pull/11070) imxrt: NXP Serial overcome race where DMA has not fetched TCD again +* [#11020](https://github.com/apache/nuttx/pull/11020) imxrt: serial Ensure the cache is updated if the DMA has updated again + +* [#11199](https://github.com/apache/nuttx/pull/11199) imx6: Replace cpu_start_t with start_t + +* [#10877](https://github.com/apache/nuttx/pull/10877) mx8mp: Add support for SPI + +* [#11203](https://github.com/apache/nuttx/pull/11203) nRF91: initial support for GNSS +* [#11308](https://github.com/apache/nuttx/pull/11308) nrf{52|53|91}: add missing support for 1 Mbps UART baud +* [#10826](https://github.com/apache/nuttx/pull/10826) nrf{52|53|91}: add support for up_perf +* [#10830](https://github.com/apache/nuttx/pull/10830) nrf{52|53|91}: fixes for timer + +* [#11172](https://github.com/apache/nuttx/pull/11172) rp2040: pwm: Fix errors at CONFIG_PWM_NCHANNELS=1 + +* [#10817](https://github.com/apache/nuttx/pull/10817) sama5: Sort SAMA5D2 adc/tsd dma +* [#10806](https://github.com/apache/nuttx/pull/10806) sama5: TSD trigger and pressure scaling issues +* [#11307](https://github.com/apache/nuttx/pull/11307) samd212: invert tx and rx in spi_dma_setup +* [#11212](https://github.com/apache/nuttx/pull/11212) samd212: sam_dmac: Fix compilation and fix SAM_DMAC_CHINTENCLR settings +* [#10855](https://github.com/apache/nuttx/pull/10855) samv7: channel gain switching in aefc +* [#11312](https://github.com/apache/nuttx/pull/11312) samv7: sam_emac: Implement errata workaround for KSZ8061 PHY + +* [#10847](https://github.com/apache/nuttx/pull/10847) {stm32|stm32f7|at32|samv7|imxrt}: fix for adc_setup +* [#11211](https://github.com/apache/nuttx/pull/11211) stm32: Add support for Ethernet packet timestamping and PTP timer +* [#11175](https://github.com/apache/nuttx/pull/11175) stm32: foc: add support for board-specific ioctl +* [#10833](https://github.com/apache/nuttx/pull/10833) stm32: Initialize LED driver during late initialization for nucleo-f446re +* [#11181](https://github.com/apache/nuttx/pull/11181) stm32: stm32/stm32_adc.c: protect irq_attach with refcounter +* [#11194](https://github.com/apache/nuttx/pull/11194) stm32: stm32_foc.c: rename some macros +* [#11194](https://github.com/apache/nuttx/pull/11194) stm32: stm32_eth: Fix excessively long critical section in ifdown handlerm +* [#10865](https://github.com/apache/nuttx/pull/10865) stm32: UART needs to be disabled before changing setup + +* [#10824](https://github.com/apache/nuttx/pull/10824) stm32l4: ADC: Adds low level operations to start and stop DMA. +* [#11154](https://github.com/apache/nuttx/pull/11154) stm32h7: serial: Do not wait on TXDMA semaphore +* [#11323](https://github.com/apache/nuttx/pull/11323) stm32h7: serial refactor out tx dma semaphore +* [#11332](https://github.com/apache/nuttx/pull/11332) stm32h7: serial Remove .txdmasem = SEM_INITIALIZER(1) bad cherry-pick +* [#10841](https://github.com/apache/nuttx/pull/10841) stm32h7: stm32_oneshot.c: Fix format warnings. +* [#11334](https://github.com/apache/nuttx/pull/11334) stm32h7: stm32h7_adc: Dynamically set clock prescaler and BOOST +* [#11367](https://github.com/apache/nuttx/pull/11367) stm32u5: fix EXTICR2,3,4 register offsets + +* [#10846](https://github.com/apache/nuttx/pull/10846) s32k1xx: Fix LPUART inversion warnings & config. +* [#10844](https://github.com/apache/nuttx/pull/10844) s32k1xx: Fix warnings in PWM code. +* [#11099](https://github.com/apache/nuttx/pull/11099) s32kxxx: flexcan doesn't set srr bit for extended frames +* [#11325](https://github.com/apache/nuttx/pull/11325) s32k3xx: NXP S32K3xx Fixes stuttering output +* [#11106](https://github.com/apache/nuttx/pull/11106) s32k3xx: serial ensure the cache is updated if the DMA has updated again +arm64 +* [#10888](https://github.com/apache/nuttx/pull/10888) Add support for FIQ interrupts +* [#11352](https://github.com/apache/nuttx/pull/11352) coredump: support arm64 coredump +* [#11200](https://github.com/apache/nuttx/pull/11200) Disable ARCH_HAVE_FORK for arm64 as a precaution +* [#11429](https://github.com/apache/nuttx/pull/11429) Fix GICv2 detection +* [#10966](https://github.com/apache/nuttx/pull/10966) Remove unnecessary code in arm64_cpu_idle.S +* [#11037](https://github.com/apache/nuttx/pull/11037) support relocate for aarch64 +* [#10917](https://github.com/apache/nuttx/pull/10917) support up_coherent_dcache function +* [#10918](https://github.com/apache/nuttx/pull/10918) target cpuid calculation error in arm64_gic_raise_sgi function +* [#11182](https://github.com/apache/nuttx/pull/11182) the bug of sscanf exception output in arm64 platform +* [#11245](https://github.com/apache/nuttx/pull/11245) vector: no need to save x0 to sp +* [#10904](https://github.com/apache/nuttx/pull/10904) XN should only be set when the attribute MT_EXECUTE_NEVER is set +risc-v +* [#10856](https://github.com/apache/nuttx/pull/10856) addrenv: utils: Determine page table flags by type of vaddr +* [#11113](https://github.com/apache/nuttx/pull/11113) addrenv: Fix static page table mapping (paddr instead of vaddr) +* [#10838](https://github.com/apache/nuttx/pull/10838) addrenv: Fix the user VMA end address +* [#10829](https://github.com/apache/nuttx/pull/10829) addrenv: Fix two SHM related issues +* [#11389](https://github.com/apache/nuttx/pull/11389) arch_elf: Check for _HI20 relocation validity +* [#11437](https://github.com/apache/nuttx/pull/11437) espressif: mcuboot: Fix dependency of the Espressif's port MCUboot. +* [#11034](https://github.com/apache/nuttx/pull/11034) espressif: Update esp-hal-3rdparty version +* [#11024](https://github.com/apache/nuttx/pull/11024) litex/litex_emac: Add support for KSZ8061 ethernet PHY. +* [#11029](https://github.com/apache/nuttx/pull/11029) litex/litex-emac: Add support for phy interrupts. +* [#11028](https://github.com/apache/nuttx/pull/11028) litex/litex_gpio: Fix ISR dispatch when using higher GPIO indexes. +* [#11365](https://github.com/apache/nuttx/pull/11365) mmu: Extend MMU Flags to 64-bit for T-Head C906 and Svpbmt +* [#11283](https://github.com/apache/nuttx/pull/11283) mpfs: corespi: Round up divider to prevent overlock of SPI +* [#10822](https://github.com/apache/nuttx/pull/10822) mpfs: corespi: Several speed optimizations to the FPGA driver +* [#10921](https://github.com/apache/nuttx/pull/10921) mpfs: ethernet: Fix RX/TX buffer and descriptor handling +* [#11405](https://github.com/apache/nuttx/pull/11405) mpfs: ethernet: Remove DMA_ENABLE hack +* [#10922](https://github.com/apache/nuttx/pull/10922) mpfs: entrypoints: Fix potential R_RISCV_JAL linker error +* [#11247](https://github.com/apache/nuttx/pull/11247) mpfs: ihc: cleanup DEBUGASSERTs and irq enabling +* [#11355](https://github.com/apache/nuttx/pull/11355) mpfs: mpfs_head.S: Change j/jal to tail call +* [#10923](https://github.com/apache/nuttx/pull/10923) mpfs: mpfs_head.S: Simplify clearing PMP +* [#11233](https://github.com/apache/nuttx/pull/11233) mpfs: opensbi: update opensbi to version 1.3.1 +* [#11404](https://github.com/apache/nuttx/pull/11404) mpfs: usb: Use kernel memory instead of user memory for DMA +* [#11403](https://github.com/apache/nuttx/pull/11403) mpfs: pmpcfg: Move PMPCFG registers to common location +* [#10875](https://github.com/apache/nuttx/pull/10875) pgalloc.h: Return kernel vaddr for kernel RAM paddr +* [#11374](https://github.com/apache/nuttx/pull/11374) riscv_pmp.c: Revert LOG2_CEIL back to run-time log2ceil function +* [#11001](https://github.com/apache/nuttx/pull/11001) Simplify PMP configuration and code +* [#11441](https://github.com/apache/nuttx/pull/11441) Update mode.h to add CSR_TVEC +sim +* [#10930](https://github.com/apache/nuttx/pull/10930) crypto: Use mbedtls default configuration without special check +* [#11381](https://github.com/apache/nuttx/pull/11381) sim_lcd: add open & close +* [#11122](https://github.com/apache/nuttx/pull/11122) sim_netdriver: some sim defconfig have problems when using the network +* [#11246](https://github.com/apache/nuttx/pull/11246) sim support 16bbp +* [#11237](https://github.com/apache/nuttx/pull/11237) simwifi: Connect the wifi whose ssid contains the special charaters. +* [#11235](https://github.com/apache/nuttx/pull/11235) simwifi: Escapes the special characters of ssid in the scan results. +* [#11069](https://github.com/apache/nuttx/pull/11069) simwifi: Fix the error of the need length for scan bssinfo. +* [#11112](https://github.com/apache/nuttx/pull/11112) simwifi: For scan results, parse and translate the Chinese ssid encoded by the wpa_cli. +* [#11066](https://github.com/apache/nuttx/pull/11066) simwifi: host wlan0 obtains ip and set dns for wlan0 in the defwan wlan0 +* [#11108](https://github.com/apache/nuttx/pull/11108) simwifi: Transfer the special characters in ssid. +* [#11104](https://github.com/apache/nuttx/pull/11104) simwifi: Support that get the connected Chinese essid. +* [#11051](https://github.com/apache/nuttx/pull/11051) simwifi: Support that simwifi connects to the hidden ssid. +* [#11171](https://github.com/apache/nuttx/pull/11171) Replace [enter|leave]_critical_section with up_irq_[save|restore] +* [#11219](https://github.com/apache/nuttx/pull/11219) Remove the wrong comment from up_allocate_heap +* [#11205](https://github.com/apache/nuttx/pull/11205) usb_rawgadget: remove halt operation +* [#10910](https://github.com/apache/nuttx/pull/10910) Update Fix more generic for platforms that do not have execinfo.h +* [#11030](https://github.com/apache/nuttx/pull/11030) wifidriver: Fix the scan error. +* [#10886](https://github.com/apache/nuttx/pull/10886) wifidriver: Support the sim wifi. +x86_64 +* [#10899](https://github.com/apache/nuttx/pull/10899) Fix idle stack assignment +xtensa +* [#11141](https://github.com/apache/nuttx/pull/11141) esp32: ble: Enable the BLE interrupt during an SPI flash operation +* [#10859](https://github.com/apache/nuttx/pull/10859) esp32: ble: Fix task_create_wrapper CPU core ID passed as argument +* [#10851](https://github.com/apache/nuttx/pull/10851) esp32: irq: Fix erroneous interrupt allocation for each CPU core +* [#11139](https://github.com/apache/nuttx/pull/11139) esp32s2: Add rtc heap support +* [#11300](https://github.com/apache/nuttx/pull/11300) esp32s2: Add RTC support +* [#11138](https://github.com/apache/nuttx/pull/11138) esp32s2: Add SPI slave support +* [#10850](https://github.com/apache/nuttx/pull/10850) esp32s2: add UART RS485 support +* [#10823](https://github.com/apache/nuttx/pull/10823) esp32s2: Add support to TWAI/CANBus controller +* [#11431](https://github.com/apache/nuttx/pull/11431) esp32s2: Add xtwdt and rwdt support +* [#10873](https://github.com/apache/nuttx/pull/10873) esp32s2: ESP32-S3 I2C improvements +* [#11259](https://github.com/apache/nuttx/pull/11259) esp32s3: Add rtc heap support +* [#11180](https://github.com/apache/nuttx/pull/11180) esp32s3: Add RWDT support +* [#11287](https://github.com/apache/nuttx/pull/11287) esp32s3: Add SPIRAM high memory support +* [#11179](https://github.com/apache/nuttx/pull/11179) esp32s3: Add XTWDT support +* [#10854](https://github.com/apache/nuttx/pull/10854) esp32s3: ble: enable the BLE interrupt during a SPI flash operation +* [#11331](https://github.com/apache/nuttx/pull/11331) esp32s3: enable LIBC_ARCH_ATOMIC +* [#11299](https://github.com/apache/nuttx/pull/11299) esp32s3: Fix esp32s3 mcuboot ota crash +* [#11136](https://github.com/apache/nuttx/pull/11136) esp32s3: Fix issue regarding IRAM-enabled ISRs by fixing the linker +* [#11285](https://github.com/apache/nuttx/pull/11285) esp32s3: Fix some ESP32S3 module reboot and QVL issues +* [#10882](https://github.com/apache/nuttx/pull/10882) esp32s3: Fix the os halt issue when esp32s3 wlan has high-speed or long time d… +* [#11427](https://github.com/apache/nuttx/pull/11427) esp32s3: Fixed bbpll not calibrated from bootloader issue +* [#11328](https://github.com/apache/nuttx/pull/11328) esp32s3: GPIO clear pending interrupt status before enable IRQ +* [#11329](https://github.com/apache/nuttx/pull/11329) esp32s3: QSPI disable DMA when sending command to slave +* [#11286](https://github.com/apache/nuttx/pull/11286) esp32s3: Invalidate cache if the flash address used has a cache mapping. +* [#11144](https://github.com/apache/nuttx/pull/11144) esp32s3: Support malloc from external RAM and internal RAM +* [#11157](https://github.com/apache/nuttx/pull/11157) esp32s3: Support multiple PHY init data bin +* [#11434](https://github.com/apache/nuttx/pull/11434) esp32s3: Support reading encrypted partitions +* [#11052](https://github.com/apache/nuttx/pull/11052) esp32s3: Support to read data from flash to PSRAM +* [#11340](https://github.com/apache/nuttx/pull/11340) esp32s3: Tasks use SPIRAM as stack can do SPI flash read/write/erase/map/unmap +* [#11428](https://github.com/apache/nuttx/pull/11428) espressif/rmt: Implement a common RMT (Remote Control) driver for xtensa-based devices. +Driver Support +New Driver Support +* [#10770](https://github.com/apache/nuttx/pull/10770) drivers: add regmap subsystems support. +* [#10902](https://github.com/apache/nuttx/pull/10902) motor: Add stepper interface +* [#11253](https://github.com/apache/nuttx/pull/11253) mtd: Adds support to W25Q20CL memory. +* [#11149](https://github.com/apache/nuttx/pull/11149) mtd: mx25rxx: add support for MX25L25673G chip +* [#11422](https://github.com/apache/nuttx/pull/11422) net: ksz9477: Add simple port-based static VLAN configuration +* [#11339](https://github.com/apache/nuttx/pull/11339) net: lan9250: Add LAN9250 driver(SPI and QSPI mode) +* [#11280](https://github.com/apache/nuttx/pull/11280) sensors: Add support for MS5607 +* [#10864](https://github.com/apache/nuttx/pull/10864) sensors: max31865:RTD-to-Digital Converter +* [#10914](https://github.com/apache/nuttx/pull/10914) stepper: add DRV8825 +* [#11228](https://github.com/apache/nuttx/pull/11228) tee: add optee client driver module +Drivers Improvements +* [#11071](https://github.com/apache/nuttx/pull/11071) Kconfigs: rename {Rpmsg|rpmsg} to RPMGS +* [#11061](https://github.com/apache/nuttx/pull/11061) can: Add new ioctls +* [#10845](https://github.com/apache/nuttx/pull/10845) foc: foc_dummy.c: update dummy device state only if dev opened +* [#11176](https://github.com/apache/nuttx/pull/11176) foc: return scaling factor for phase currents and BEMF via ioctl +* [#10808](https://github.com/apache/nuttx/pull/10808) ioexpander: Minor fix for ioexpander driver +* [#11147](https://github.com/apache/nuttx/pull/11147) lcd: add stride support for LCD driver +* [#11185](https://github.com/apache/nuttx/pull/11185) lcd: change lcd stride from pixel to bytes +* [#10926](https://github.com/apache/nuttx/pull/10926) math: mpi: add mpi driver in math +* [#11240](https://github.com/apache/nuttx/pull/11240) misc: Rpmsgblk function optimization +* [#11220](https://github.com/apache/nuttx/pull/11220) mmcsd: mmcsd_sdinitialize should save csd register into priv->csd +* [#10909](https://github.com/apache/nuttx/pull/10909) mtd: filemtd:Fix teardown return error number EINVAL +* [#11041](https://github.com/apache/nuttx/pull/11041) mtd: get mtd_geometry_s.model for mtd partition and optimize code +* [#11187](https://github.com/apache/nuttx/pull/11187) mtd: s25fl1: fix compile warnings caused by incorrect variable print format +* [#11370](https://github.com/apache/nuttx/pull/11370) mtd: w25q: add nxsig_usleep to busy waiting in w25qxxxjv_erase_sector() +* [#11391](https://github.com/apache/nuttx/pull/11391) net: qemu/wifi: Add the virtual wifi function on the emulator. +* [#11216](https://github.com/apache/nuttx/pull/11216) net: skeleton.c doesn't compile without this patch if ioctls are enabled +* [#10907](https://github.com/apache/nuttx/pull/10907) note: Change 0/1 to false/true +* [#11153](https://github.com/apache/nuttx/pull/11153) note: delete sched_note_flatten +* [#10840](https://github.com/apache/nuttx/pull/10840) note: optimize note performance +* [#10920](https://github.com/apache/nuttx/pull/10920) note: remove remaining event code +* [#11074](https://github.com/apache/nuttx/pull/11074) power: pm: use pm_staytimeout() in greedy_governor_activity() +* [#11132](https://github.com/apache/nuttx/pull/11132) rptun: check the status before stop remote proc +* [#11222](https://github.com/apache/nuttx/pull/11222) rtc: RTC driver improvement +* [#10831](https://github.com/apache/nuttx/pull/10831) rtt: make RTT console optional +* [#11296](https://github.com/apache/nuttx/pull/11296) segger: rtt: correct macro name to avoid unable to change default mode +* [#11419](https://github.com/apache/nuttx/pull/11419) sensors: mx56xx: Add support for second order compensation +* [#11426](https://github.com/apache/nuttx/pull/11426) sensors: mx56xx: Fix threshold and calculation +* [#11178](https://github.com/apache/nuttx/pull/11178) serial: uart_tcsendbreak: Remove cancel point, as tcsendbreak is not one +* [#11402](https://github.com/apache/nuttx/pull/11402) syslog: ramlog: improve ramlog performance +* [#11392](https://github.com/apache/nuttx/pull/11392) syslog: ramlog: multi readers +* [#10890](https://github.com/apache/nuttx/pull/10890) syslog: ramlog: remove sched_[un]lock and rl_nwaiters +* [#11186](https://github.com/apache/nuttx/pull/11186) timers: Rewrite adjtime() implementation to work for RTC and tickless kernel +* [#11356](https://github.com/apache/nuttx/pull/11356) usbdev: Add callback for CONFIG_USBDEV_SOFINTERRUPT +* [#11042](https://github.com/apache/nuttx/pull/11042) usbdev: config USBDEV_TRACE_INITIALIDSET when disbale USBDEV_TRACE +* [#11161](https://github.com/apache/nuttx/pull/11161) usbdev: Solve some problems of USB hotplug +* [#10985](https://github.com/apache/nuttx/pull/10985) usrsock: Make the field of usrsock_request native alignment +* [#11103](https://github.com/apache/nuttx/pull/11103) usrsock: rpmsg_server: Keep msg order in recursive call +* [#11107](https://github.com/apache/nuttx/pull/11107) usrsock: socket fallback with ENETDOWN +* [#10874](https://github.com/apache/nuttx/pull/10874) video: fb: Add fb_register_device +* [#10812](https://github.com/apache/nuttx/pull/10812) video: goldfish: Remove the vsync residual code +* [#11380](https://github.com/apache/nuttx/pull/11380) video: goldfish: optimize goldfish fb register +* [#11249](https://github.com/apache/nuttx/pull/11249) video: video.c: modify set_buf call seqence in start_capture function. +* [#11224](https://github.com/apache/nuttx/pull/11224) video: wait when the vsync queue is full in FBIO_WAITFORVSYNC +* [#11382](https://github.com/apache/nuttx/pull/11382) virtio: Support for setting MAC addresses of the virtio-net interfaces +* [#11385](https://github.com/apache/nuttx/pull/11385) virtio: virtio-gpu: convert virito-gpu fb_register to virtio_gpu_fb_register +* [#11201](https://github.com/apache/nuttx/pull/11201) virtio: Virtio Qemu 8.1.2 issues fix +* [#11013](https://github.com/apache/nuttx/pull/11013) wireless: bluetooth: Add option to set the HCI TX thread affinity while running with SMP enabled +* [#11072](https://github.com/apache/nuttx/pull/11072) wireless: bluetooth: rpmsg depends on RPTUN + +Board Support +New Board Support +arm +* [#10987](https://github.com/apache/nuttx/pull/10987) gd32f4: add gd32f470i board support +* [#11094](https://github.com/apache/nuttx/pull/11094) stm32: add support to LINUM-STM32H753BI board +* [#10990](https://github.com/apache/nuttx/pull/10990) stm32: add support to STM32F401RC-RS485 board +* [#11358](https://github.com/apache/nuttx/pull/11358) stm32h7: linum-stm32h753bi: Add modbus example using usart6 +* [#11276](https://github.com/apache/nuttx/pull/11276) seeed-xiao-rp2040: Add initial board support + +xtensa +* [#10976](https://github.com/apache/nuttx/pull/10976) Add ESP32-2432S028 board +* [#10928](https://github.com/apache/nuttx/pull/10928) esp32s3-box: Support hardware version 3 + +risc-v +* [#11379](https://github.com/apache/nuttx/pull/11379) Initial support for CanMV-k230 board +* [#11377](https://github.com/apache/nuttx/pull/11377) Add support for PINE64 Ox64 BL808 SBC + +Board Improvements +* [#11056](https://github.com/apache/nuttx/pull/11056) Modify test "ramtest" path +* [#11192](https://github.com/apache/nuttx/pull/11192) remove obsolete CONFIG_EXAMPLES_FOC_IPHASE_ADC option + +arm +* [#11101](https://github.com/apache/nuttx/pull/11101) cxd56xx: Add cxd5610 gnss driver + +* [#11373](https://github.com/apache/nuttx/pull/11373) gd32f4xx: change gd32f470z board code + +* [#11193](https://github.com/apache/nuttx/pull/11193) imx6: Fix sabre-6quad:libcxx + +* [#11310](https://github.com/apache/nuttx/pull/11310) nrf52: nrf52832-dk: add timer example +* [#10835](https://github.com/apache/nuttx/pull/10835) nrf52: remove CONFIG_ARMV7M_SYSTICK form tickless configs + +* [#11150](https://github.com/apache/nuttx/pull/11150) sama5: Add QSPI support SAMA5 +* [#11151](https://github.com/apache/nuttx/pull/11151) sama5: sama5d2-xult: add support for QSPI flash and nxffs + +* [#11117](https://github.com/apache/nuttx/pull/11117) stm32: b-g431b-esc1: don't use CONFIG_STM32_USE_LEGACY_PINMAP=y +* [#11306](https://github.com/apache/nuttx/pull/11306) stm32h7: fix config conflict +* [#11214](https://github.com/apache/nuttx/pull/11214) stm32h7: linum-stm32h753bi: Add support to RTC and alarm +* [#11167](https://github.com/apache/nuttx/pull/11167) stm32h7: linum-stm32h753bi: Added suport to userlerds library. +* [#11265](https://github.com/apache/nuttx/pull/11265) stm32f4: stm32f401rc-rs485: Add sdcard support +* [#11217](https://github.com/apache/nuttx/pull/11217) stm32f4: stm32f401rc-rs485: Add buttons support +* [#11169](https://github.com/apache/nuttx/pull/11169) stm32f4: stm32f401rc-rs485: add support to userleds +* [#11255](https://github.com/apache/nuttx/pull/11255) stm32f4: stm32f401rc-rs485: Fix f401rc flash size +risc-v +* [#10736](https://github.com/apache/nuttx/pull/10736) esp32c3: pm: Let PM_PROCFS depend on FS_PROCFS_REGISTER +* [#11418](https://github.com/apache/nuttx/pull/11418) esp32c6: Add ostest defconfig +* [#11096](https://github.com/apache/nuttx/pull/11096) mpfs: Add option for board specific PMP configuration +* [#11262](https://github.com/apache/nuttx/pull/11262) qemu-rv: rv-virt/knsh: Set correct RAM_START and RAM_SIZE +* [#11397](https://github.com/apache/nuttx/pull/11397) qemu-rv: Virtio sound +sim +* [#10960](https://github.com/apache/nuttx/pull/10960) fix Cygwin/MSYS2 ld: unrecognized option '-z' +* [#11290](https://github.com/apache/nuttx/pull/11290) nxscope: remove CONFIG_ALLSYMS=y +xtensa +* [#11142](https://github.com/apache/nuttx/pull/11142) esp32: Add LVGL defconfig +* [#11229](https://github.com/apache/nuttx/pull/11229) esp32: Add support enconder to ESP32-2432S028 +* [#10961](https://github.com/apache/nuttx/pull/10961) esp32: Add wifishare board config and documentation +* [#10996](https://github.com/apache/nuttx/pull/10996) esp32: Rename Shift game to Brickmatch and add an board example to esp32-devkitc +* [#11417](https://github.com/apache/nuttx/pull/11417) esp32<|s2|s3>_board_spiflash: Fix error message about SmartFS init +* [#11425](https://github.com/apache/nuttx/pull/11425) esp32s2: Increase init task stack size to 3072 +* [#11156](https://github.com/apache/nuttx/pull/11156) esp32s3: Link stack checking function and data to SRAM when enable flash or PSRAM driver +* [#11342](https://github.com/apache/nuttx/pull/11342) esp32s3: add esp32s3-devkit:toywasm kconfig +* [#11295](https://github.com/apache/nuttx/pull/11295) esp32s3: Add rtc defconfig +* [#10885](https://github.com/apache/nuttx/pull/10885) ESP32S3-EYE: GPIO and button support +* [#10884](https://github.com/apache/nuttx/pull/10884) ESP32-S3-EYE: I2C, SPI and LCD support +* [#10883](https://github.com/apache/nuttx/pull/10883) ESP32-S3-EYE: Wifi +File System +Improvements +* [#10995](https://github.com/apache/nuttx/pull/10995) Change inode_checkflags to static function +* [#11445](https://github.com/apache/nuttx/pull/11445) Fix hostfs after uid/gid changes +* [#11433](https://github.com/apache/nuttx/pull/11433) fat: Fix number of data clusters usable for fat driver +* [#11196](https://github.com/apache/nuttx/pull/11196) fat: fix ubsan warning of shift-out-of-bounds +* [#10706](https://github.com/apache/nuttx/pull/10706) fs_epoll: several epoll problems fix +* [#11125](https://github.com/apache/nuttx/pull/11125) fs_files.c: make sure that fs_getfilep is not interrupted when holding mutex +* [#11349](https://github.com/apache/nuttx/pull/11349) fs_gettype:add zipfs magic +* [#11446](https://github.com/apache/nuttx/pull/11446) hostfs:fix structure layout inconsistency in hostfs +* [#11090](https://github.com/apache/nuttx/pull/11090) inode: Change inode_unlink to static function +* [#11188](https://github.com/apache/nuttx/pull/11188) inode: check file list before memcpy +* [#11140](https://github.com/apache/nuttx/pull/11140) inode: improve the performance of get file pointer +* [#11318](https://github.com/apache/nuttx/pull/11318) proc: Fix groupfd to get fd by group instead of current tcb +* [#11449](https://github.com/apache/nuttx/pull/11449) procfs add poll support +* [#11360](https://github.com/apache/nuttx/pull/11360) procfs/cpuinfo: Zero copylen in cpuinfo_read +* [#11039](https://github.com/apache/nuttx/pull/11039) rename: fix use after free issue about rename +* [#11451](https://github.com/apache/nuttx/pull/11451) smartfs: Add necessary aligned access in smartfs_rename() +* [#11248](https://github.com/apache/nuttx/pull/11248) spiffs: correct mutex lock cycle of spiffs +* [#10804](https://github.com/apache/nuttx/pull/10804) support zipfs,can mount zipfile +* [#11232](https://github.com/apache/nuttx/pull/11232) tmpfs: fix an integer overflow +* [#10880](https://github.com/apache/nuttx/pull/10880) vfs: add munmap logic to pseudofs + +Networking +Improvements +* [#10813](https://github.com/apache/nuttx/pull/10813) Add CONFIG_NET_ICMPv6_ROUTER_LIFETIME +* [#10893](https://github.com/apache/nuttx/pull/10893) allow icmpv6 and udp to find the dev by the ifindex with s_boundto. +* [#10916](https://github.com/apache/nuttx/pull/10916) Fix RNDIS compilation error +* [#10819](https://github.com/apache/nuttx/pull/10819) local: Fix the problem that local udp socketpair cannot release fifo files. +* [#11443](https://github.com/apache/nuttx/pull/11443) local: make the call return of each process consistent with linux +* [#11015](https://github.com/apache/nuttx/pull/11015) local: Support SO_SNDBUF option in getsockopt +* [#11289](https://github.com/apache/nuttx/pull/11289) loopback: Fix flags of lo device +* [#11324](https://github.com/apache/nuttx/pull/11324) icmpv6:Optimize the process of obtaining the IPv6 address through RA. +* [#11010](https://github.com/apache/nuttx/pull/11010) icmpv6: Fix net mask logic in icmpv6_setaddresses +* [#11197](https://github.com/apache/nuttx/pull/11197) igmp: call IFF_SET_IPv4 when igmp_send +* [#11384](https://github.com/apache/nuttx/pull/11384) ipv6: Fix source address with many addresses in same network +* [#11378](https://github.com/apache/nuttx/pull/11378) ipv6: Move xxx_ipv6multicast from arch to common code +* [#10894](https://github.com/apache/nuttx/pull/10894) netdb: When set a dns nameserver which already exists, retrun OK +* [#11076](https://github.com/apache/nuttx/pull/11076) netconfig: Enable SOCK_CLOEXEC for ioctl sockets +* [#11396](https://github.com/apache/nuttx/pull/11396) netdev: Modify the logic for setting the IFF_RUNNING status of interfaces. +* [#11110](https://github.com/apache/nuttx/pull/11110) Simplify getting value for different domain +* [#11054](https://github.com/apache/nuttx/pull/11054) Support multiple IPv6 address per netdev +* [#11406](https://github.com/apache/nuttx/pull/11406) tcp: Recover from iob shortage with TCP_WRITE_BUFFERS +* [#11126](https://github.com/apache/nuttx/pull/11126) tcp: Support initial sequence number described in RFC 6528 +* [#11009](https://github.com/apache/nuttx/pull/11009) tun: Fix the error of calling tun_close when tun_txavail or tun_txavail_work is executed +* [#10986](https://github.com/apache/nuttx/pull/10986) tun: Fix the error of calling tun_close when tun_txavail or tun_txavail_work is executed +* [#11372](https://github.com/apache/nuttx/pull/11372) udp: Add check when sending too big packet without IP frag +* [#11210](https://github.com/apache/nuttx/pull/11210) udp: Add support for SO_TIMESTAMP +* [#11120](https://github.com/apache/nuttx/pull/11120) udp: modify ipv4 multicast to allow different conn to join simultaneously +* [#10878](https://github.com/apache/nuttx/pull/10878) usersock: Return -ENOSUPP directly if domain isn't equal to PF_INET/PF_INET6 +Security Issues Fixed In This Release +Compatibility Concerns +* [#10605](https://github.com/apache/nuttx/pull/10605)  Implement ticket spinlock + +A proposal to slove #1488 + +Implement ticket spinlock. + + +* [#10861](https://github.com/apache/nuttx/pull/10861) spinlock: Add spin_lock_init and spin_is_locked macro + +align with Linux api naming. + + +* [#11102](https://github.com/apache/nuttx/pull/11102) sched: explicitly select the cpuload clock source configuration + +Different configurations require different dependencies. +Explicitly select dependencies to avoid automatically selecting +inappropriate configurations. + +* [#11334](https://github.com/apache/nuttx/pull/11334) stm32h7_adc: Dynamically set clock prescaler and BOOST + +First commit is aligning naming and is a breaking change. + +* [#10827](https://github.com/apache/nuttx/pull/10827) Improve adjtime() functionality + +Prior pull request #9084 and issue #8858 added basic adjtime() +support for the SAMv7 platform. + +This pull request adds support for STM32 platform. + +In addition I have made a few changes to the adjtime() configuration +options: + +1) Previously adjustments less than 1 microsecond per tick would be +   completely ignored. Now they are applied over a shorter period at +   a rate of 1 us per tick. + +2) Previously CLOCK_ADJTIME_PERIOD was in units of 1/100th of second. +   Change to milliseconds to be more generally useful unit. +   Change setting name to CLOCK_ADJTIME_PERIOD_MS to make the unit change +   easier to notice. + +3) Previously CLOCK_ADJTIME_SLEWLIMIT was in percentage. +   Most clock crystals have better accuracy than 1%, so the minimum slew +   rate was excessive. Change to CLOCK_ADJTIME_SLEWLIMIT_PPM with setting +   value in parts per million. + +4) No need to use floating point math in clock_adjtime.c. + +Impact + +Users who have used CLOCK_ADJTIME_PERIOD and CLOCK_ADJTIME_SLEWLIMIT  +settings should update their configuration. New CLOCK_ADJTIME_PERIOD_MS is +10x the old period value, and new CLOCK_ADJTIME_SLEWLIMIT_PPM is 10000 times +the old slewlimit. \ No newline at end of file diff --git a/Documentation/platforms/arm64/imx9/boards/imx93-evk/README.txt b/Documentation/platforms/arm64/imx9/boards/imx93-evk/README.txt new file mode 100644 index 0000000000000..1a377d76f0f0d --- /dev/null +++ b/Documentation/platforms/arm64/imx9/boards/imx93-evk/README.txt @@ -0,0 +1,145 @@ +README.txt +========== + +The kit i.MX93 Evaluation Kit has a pre-installed Linux image which contains +u-boot and the i.MX93 reference Linux installation. + +u-boot is required to boot NuttX (for now) as it initializes the hardware for +us, i.e. DDR, clocks, I/O muxes etc. + +========================================== + +How to run nuttx on i.MX93 Evaluation Kit. + +========================================== + +Below is a set of instructions on how to run NuttX on the i.MX93 EVK + +========================================== + +Pre-requisites + +========================================== + +- imx93_ca55.JLinkScript which is a custom file, put it wherever you want + +========================================== + +U-Boot configuration + +========================================== + +Two things need to be configured on u-boot before NuttX can be loaded: + +- u-boot data cache must be turned off +- u-boot must stop to the u-boot console, i.e. the Linux payload must not be loaded + +Manual option: + +1. Disable u-boot autostart (needs to be done only once): + + Hit any key to stop autoboot: 0 + u-boot=> setenv bootdelay -1 + u-boot=> saveenv + Saving Environment to MMC... Writing to MMC(0)... OK + u-boot=> reset + +2. On every boot, the data cache must be disabled for options 2 and 3 to work + + u-boot=> dcache off + +Automated option: + +1. Replace the default bootcmd to disable dcache automatically: + + u-boot=> setenv bootcmd dcache off + u-boot=> saveenv + Saving Environment to MMC... Writing to MMC(0)... OK + u-boot=> reset + +To restore the default bootcmd which starts Linux automatically: + + u-boot=> setenv bootcmd run distro_bootcmd;run bsp_bootcmd + u-boot=> saveenv + Saving Environment to MMC... Writing to MMC(0)... OK + u-boot=> reset + +The default bootcmd is: + +u-boot=> env print bootcmd +bootcmd=run distro_bootcmd;run bsp_bootcmd + +========================================== + +Loading and running the NuttX image + +========================================== + +You have three options: + +1 - Load via u-boot from SD-card +2 - Load via gdb +3 - Load via JLink + +========================================== + +Option 1: load via u-boot from SD-card: + +========================================== + +1. Build nuttx, and move nuttx.bin to SD-card + +2. Load from SD-card and start nuttx payload + + u-boot=> dcache off; fatload mmc 1 0x80000000 nuttx.bin; go 0x80000000 + +========================================== + +Option 2: start via gdb: + +========================================== + +1. Start JLinkGDBServer + + JLinkGDBServer -device CORTEX-A55 -JLinkScriptFile /imx93_ca55.JLinkScript + +2. Start gdb + + $ aarch64-none-elf-gdb + + 2.1 Attach and load nuttx + + (gdb) target remote localhost:2331 + (gdb) set mem inaccessible-by-default off + (gdb) load /nuttx + (gdb) monitor go + +========================================== + +Option 3: load with JLink: + +========================================== + +1. Start JLink + + $ JLinkExe -device CORTEX-A55 -if JTAG -jtagconf -1,-1 -speed 4000 -JLinkScriptFile /imx93_ca55.JLinkScript + + 1.1 Add -AutoConnect 1 to connect automatically + + $ JLinkExe -device CORTEX-A55 -if JTAG -jtagconf -1,-1 -speed 4000 -JLinkScriptFile /imx93_ca55.JLinkScript -AutoConnect 1 + +2. Connect JLink + + 2.1 Connect to the debugger + + Type "connect" to establish a target connection, '?' for help + J-Link>connect + + You should now have a JLink prompt. + + Cortex-A55 identified. + J-Link> + +3. Load nuttx. Note that JLink expects the .elf extension, the default build output of nuttx is just "nuttx" without the extension, so it must be added to the file... + + J-Link>LoadFile /nuttx.elf diff --git a/Documentation/platforms/arm64/imx9/boards/imx93-evk/index.rst b/Documentation/platforms/arm64/imx9/boards/imx93-evk/index.rst new file mode 100644 index 0000000000000..97ed448898f19 --- /dev/null +++ b/Documentation/platforms/arm64/imx9/boards/imx93-evk/index.rst @@ -0,0 +1,6 @@ +========== +imx93-evk +========== + +.. include:: README.txt + :literal: diff --git a/Documentation/platforms/arm64/imx9/index.rst b/Documentation/platforms/arm64/imx9/index.rst new file mode 100644 index 0000000000000..4b1e5b7412014 --- /dev/null +++ b/Documentation/platforms/arm64/imx9/index.rst @@ -0,0 +1,12 @@ +========= +NXP i.MX9 +========= + +Supported Boards +================ + +.. toctree:: + :glob: + :maxdepth: 1 + + boards/*/* diff --git a/arch/arm/src/armv7-a/CMakeLists.txt b/arch/arm/src/armv7-a/CMakeLists.txt index 543cc6e235616..72c05b46f053c 100644 --- a/arch/arm/src/armv7-a/CMakeLists.txt +++ b/arch/arm/src/armv7-a/CMakeLists.txt @@ -75,8 +75,14 @@ else() endif() if(CONFIG_ARCH_ADDRENV) - list(APPEND SRCS arm_addrenv.c arm_addrenv_utils.c arm_addrenv_perms.c - arm_pgalloc.c) + list( + APPEND + SRCS + arm_addrenv.c + arm_addrenv_utils.c + arm_addrenv_perms.c + arm_pgalloc.c + arm_addrenv_pgmap.c) if(CONFIG_ARCH_STACK_DYNAMIC) list(APPEND SRCS arm_addrenv_ustack.c) endif() diff --git a/arch/arm/src/armv7-a/Make.defs b/arch/arm/src/armv7-a/Make.defs index 6ea56bba38849..3bdcd77a86d6b 100644 --- a/arch/arm/src/armv7-a/Make.defs +++ b/arch/arm/src/armv7-a/Make.defs @@ -66,6 +66,7 @@ endif ifeq ($(CONFIG_ARCH_ADDRENV),y) CMN_CSRCS += arm_addrenv.c arm_addrenv_utils.c arm_addrenv_perms.c arm_pgalloc.c + CMN_CSRCS += arm_addrenv_pgmap.c ifeq ($(CONFIG_ARCH_STACK_DYNAMIC),y) CMN_CSRCS += arm_addrenv_ustack.c endif diff --git a/arch/arm/src/armv7-a/arm_addrenv_pgmap.c b/arch/arm/src/armv7-a/arm_addrenv_pgmap.c new file mode 100644 index 0000000000000..3ced8813fecbd --- /dev/null +++ b/arch/arm/src/armv7-a/arm_addrenv_pgmap.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * arch/arm/src/armv7-a/arm_addrenv_pgmap.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "pgalloc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_addrenv_page_vaddr + * + * Description: + * Find the kernel virtual address associated with physical page. + * + * Input Parameters: + * page - The page physical address. + * + * Returned Value: + * Page kernel virtual address on success; NULL on failure. + * + ****************************************************************************/ + +uintptr_t up_addrenv_page_vaddr(uintptr_t page) +{ + return arm_pgvaddr(page); +} + +/**************************************************************************** + * Name: up_addrenv_page_wipe + * + * Description: + * Wipe a page of physical memory, first mapping it into kernel virtual + * memory. + * + * Input Parameters: + * page - The page physical address. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void up_addrenv_page_wipe(uintptr_t page) +{ + uintptr_t vaddr = arm_pgvaddr(page); + memset((void *)vaddr, 0, MM_PGSIZE); +} diff --git a/arch/arm/src/imxrt/imxrt_enet.c b/arch/arm/src/imxrt/imxrt_enet.c index df8a72489c835..e4c8889ceb4d0 100644 --- a/arch/arm/src/imxrt/imxrt_enet.c +++ b/arch/arm/src/imxrt/imxrt_enet.c @@ -200,6 +200,8 @@ # error "Need at least one RX buffer" #endif +#define nitems(_a) (sizeof(_a) / sizeof(0[(_a)])) + /* From ref manual TDSR/RDSR description * For optimal performance the pointer should be 512-bit aligned, that is, * evenly divisible by 64. @@ -250,8 +252,25 @@ * ...and further PHY descriptions here. */ -#if defined(CONFIG_ETH0_PHY_KSZ8081) -# define BOARD_PHY_NAME "KSZ8081" +#if defined(CONFIG_ETH0_PHY_MULTI) +# if !defined(BOARD_ETH0_PHY_LIST) +# error "CONFIG_ETH0_PHY_MULTI requires board.h to define BOARD_ETH0_PHY_LIST!" +# endif +# define BOARD_PHY_NAME g_board_phys[priv->current_phy].name +# define BOARD_PHYID1 g_board_phys[priv->current_phy].id1 +# define BOARD_PHYID2 g_board_phys[priv->current_phy].id2 +# define BOARD_PHY_STATUS g_board_phys[priv->current_phy].status +# define BOARD_PHY_ADDR priv->current_phy_address +# define BOARD_PHY_10BASET(s) (imxrt_phy_status(priv, (s), g_board_phys[priv->current_phy].mbps10) != 0) +# define BOARD_PHY_100BASET(s) (imxrt_phy_status(priv, (s), g_board_phys[priv->current_phy].mbps100) != 0) +# define BOARD_PHY_ISDUPLEX(s) (imxrt_phy_status(priv, (s), g_board_phys[priv->current_phy].duplex) != 0) +# define BOARD_PHY_ISCLAUSE45() (g_board_phys[priv->current_phy].clause == 45) +# define CLAUSE45 +# define MMD1 1 +# define MMD1_PMA_STATUS1 1 +# define MMD1_PS1_RECEIVE_LINK_STATUS (1 << 2) +#elif defined(CONFIG_ETH0_PHY_KSZ8081) +# define BOARD_PHY_NAME MII_KSZ8081_NAME # define BOARD_PHYID1 MII_PHYID1_KSZ8081 # define BOARD_PHYID2 MII_PHYID2_KSZ8081 # define BOARD_PHY_STATUS MII_KSZ8081_PHYCTRL1 @@ -260,7 +279,7 @@ # define BOARD_PHY_100BASET(s) (((s) & MII_PHYCTRL1_MODE_100HDX) != 0) # define BOARD_PHY_ISDUPLEX(s) (((s) & MII_PHYCTRL1_MODE_DUPLEX) != 0) #elif defined(CONFIG_ETH0_PHY_LAN8720) -# define BOARD_PHY_NAME "LAN8720" +# define BOARD_PHY_NAME MII_LAN8720_NAME # define BOARD_PHYID1 MII_PHYID1_LAN8720 # define BOARD_PHYID2 MII_PHYID2_LAN8720 # define BOARD_PHY_STATUS MII_LAN8720_SCSR @@ -269,7 +288,7 @@ # define BOARD_PHY_100BASET(s) (((s)&MII_LAN8720_SPSCR_100MBPS) != 0) # define BOARD_PHY_ISDUPLEX(s) (((s)&MII_LAN8720_SPSCR_DUPLEX) != 0) #elif defined(CONFIG_ETH0_PHY_LAN8742A) -# define BOARD_PHY_NAME "LAN8742A" +# define BOARD_PHY_NAME MII_LAN8742A_NAME # define BOARD_PHYID1 MII_PHYID1_LAN8742A # define BOARD_PHYID2 MII_PHYID2_LAN8742A # define BOARD_PHY_STATUS MII_LAN8740_SCSR @@ -278,7 +297,7 @@ # define BOARD_PHY_100BASET(s) (((s)&MII_LAN8720_SPSCR_100MBPS) != 0) # define BOARD_PHY_ISDUPLEX(s) (((s)&MII_LAN8720_SPSCR_DUPLEX) != 0) #elif defined(CONFIG_ETH0_PHY_DP83825I) -# define BOARD_PHY_NAME "DP83825I" +# define BOARD_PHY_NAME MII_DP83825I_NAME # define BOARD_PHYID1 MII_PHYID1_DP83825I # define BOARD_PHYID2 MII_PHYID2_DP83825I # define BOARD_PHY_STATUS MII_DP83825I_PHYSTS @@ -287,7 +306,7 @@ # define BOARD_PHY_100BASET(s) (((s) & MII_DP83825I_PHYSTS_SPEED) == 0) # define BOARD_PHY_ISDUPLEX(s) (((s) & MII_DP83825I_PHYSTS_DUPLEX) != 0) #elif defined(CONFIG_ETH0_PHY_TJA1103) -# define BOARD_PHY_NAME "TJA1103" +# define BOARD_PHY_NAME MII_TJA1103_NAME # define BOARD_PHYID1 MII_PHYID1_TJA1103 # define BOARD_PHYID2 MII_PHYID2_TJA1103 # define BOARD_PHY_STATUS MII_TJA110X_BSR @@ -300,7 +319,7 @@ # define MMD1_PMA_STATUS1 1 # define MMD1_PS1_RECEIVE_LINK_STATUS (1 << 2) #elif defined(CONFIG_ETH0_PHY_YT8512) -# define BOARD_PHY_NAME "YT8512" +# define BOARD_PHY_NAME MII_YT8512_NAME # define BOARD_PHYID1 MII_PHYID1_YT8512 # define BOARD_PHYID2 MII_PHYID2_YT8512 # define BOARD_PHY_STATUS MII_YT8512_PHYSTS @@ -375,6 +394,10 @@ struct imxrt_driver_s struct enet_desc_s *txdesc; /* A pointer to the list of TX descriptor */ struct enet_desc_s *rxdesc; /* A pointer to the list of RX descriptors */ +#if defined(CONFIG_ETH0_PHY_MULTI) + uint8_t current_phy; /* The index of the PHY being used */ + uint8_t current_phy_address; /* The address of the PHY being used */ +#endif /* This holds the information visible to the NuttX network */ struct net_driver_s dev; /* Interface understood by the network */ @@ -384,6 +407,15 @@ struct imxrt_driver_s * Private Data ****************************************************************************/ +/* BOARD_ETH0_PHY_LIST provided by the board.h for CONFIG_ETH0_PHY_MULTI */ + +#if defined(CONFIG_ETH0_PHY_MULTI) +const struct phy_desc_s g_board_phys[] = + { + BOARD_ETH0_PHY_LIST + }; +#endif + static struct imxrt_driver_s g_enet[CONFIG_IMXRT_ENET_NETHIFS]; /* The DMA descriptors */ @@ -470,6 +502,13 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, /* PHY/MII support */ +#if defined(CONFIG_ETH0_PHY_MULTI) +static int imxrt_phy_is(struct imxrt_driver_s *priv, const char *name); +static int imxrt_phy_status(struct imxrt_driver_s *priv, int phydata, + uint16_t mask); +static int imxrt_determine_phy(struct imxrt_driver_s *priv); +#endif + #if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) static int imxrt_phyintenable(struct imxrt_driver_s *priv); #endif @@ -1377,6 +1416,15 @@ static int imxrt_ifup_action(struct net_driver_s *dev, bool resetphy) /* Configure the PHY */ +#if defined(CONFIG_ETH0_PHY_MULTI) + ret = imxrt_determine_phy(priv); + if (ret < 0) + { + nerr("ERROR: Failed to determine the PHY: %d\n", ret); + return ret; + } +#endif + ret = imxrt_initphy(priv, resetphy); if (ret < 0) { @@ -1872,7 +1920,11 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) struct mii_ioctl_data_s *req = (struct mii_ioctl_data_s *)((uintptr_t)arg); #if defined(CLAUSE45) - if (MII_MSR == req->reg_num) + if ( +# if defined(CONFIG_ETH0_PHY_MULTI) + BOARD_PHY_ISCLAUSE45() && +# endif + MII_MSR == req->reg_num) { ret = imxrt_readmmd(priv, req->phy_id, MMD1, MMD1_PMA_STATUS1, &req->val_out); @@ -1926,46 +1978,60 @@ static int imxrt_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) #if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT) static int imxrt_phyintenable(struct imxrt_driver_s *priv) { +#if defined(CONFIG_ETH0_PHY_KSZ8051) || defined(CONFIG_ETH0_PHY_KSZ8061) || \ + defined(CONFIG_ETH0_PHY_KSZ8081) || defined(CONFIG_ETH0_PHY_DP83825I) || \ + defined(CONFIG_ETH0_YT8512) || defined(CONFIG_ETH0_PHY_MULTI) + uint16_t phyval; int ret; -#if defined(CONFIG_ETH0_PHY_KSZ8051) || defined(CONFIG_ETH0_PHY_KSZ8061) || \ - defined(CONFIG_ETH0_PHY_KSZ8081) || defined(CONFIG_ETH0_PHY_DP83825I) + /* Compile time Kzxxxx defaults */ - /* Read the interrupt status register in order to clear any pending - * interrupts - */ + uint16_t mask = MII_KSZ80X1_INT_LDEN | MII_KSZ80X1_INT_LUEN; + uint8_t rreg = MII_KSZ8081_INT; + uint8_t wreg = rreg; - ret = imxrt_readmii(priv, priv->phyaddr, MII_KSZ8081_INT, &phyval); - if (ret == OK) - { - /* Enable link up/down interrupts */ + /* Compile time YT8512 defaults */ +# if defined(CONFIG_ETH0_YT8512) + mask = MII_YT8512_IMR_LD_EN | MII_YT8512_IMR_LU_EN; + rreg = MII_YT8512_ISR; + wreg = MII_YT8512_IMR; +# endif - ret = imxrt_writemii(priv, priv->phyaddr, MII_KSZ8081_INT, - (MII_KSZ80X1_INT_LDEN | MII_KSZ80X1_INT_LUEN)); + /* Run time YT8512 defaults */ +# if defined(CONFIG_ETH0_PHY_MULTI) + if (imxrt_phy_is(priv, MII_YT8512_NAME)) + { + mask = MII_YT8512_IMR_LD_EN | MII_YT8512_IMR_LU_EN; + rreg = MII_YT8512_ISR; + wreg = MII_YT8512_IMR; } - - return ret; -#elif defined(CONFIG_ETH0_YT8512) + else if (!(imxrt_phy_is(priv, MII_KSZ8051_NAME) || + imxrt_phy_is(priv, MII_KSZ8061_NAME) || + imxrt_phy_is(priv, MII_KSZ8081_NAME) || + imxrt_phy_is(priv, MII_DP83825I_NAME))) + { + return -ENOSYS; + } +# endif /* Read the interrupt status register in order to clear any pending * interrupts */ - ret = imxrt_readmii(priv, priv->phyaddr, MII_YT8512_ISR, &phyval); + ret = imxrt_readmii(priv, priv->phyaddr, rreg, &phyval); if (ret == OK) { /* Enable link up/down interrupts */ - ret = imxrt_writemii(priv, priv->phyaddr, MII_YT8512_IMR, - (MII_YT8512_IMR_LD_EN | MII_YT8512_IMR_LU_EN)); + ret = imxrt_writemii(priv, priv->phyaddr, wreg, mask); } return ret; #else # error Unrecognized PHY return -ENOSYS; -#endif +# endif } #endif @@ -2121,6 +2187,126 @@ static int imxrt_readmii(struct imxrt_driver_s *priv, uint8_t phyaddr, return OK; } +#if defined(CONFIG_ETH0_PHY_MULTI) +/**************************************************************************** + * Function: imxrt_determine_phy + * + * Description: + * Uses the board.h supplied PHY list to determine which PHY + * is populated on this board. + * + * Input Parameters: + * priv - Reference to the private ENET driver state structure + * + * Returned Value: + * Zero on success, a -ENOENT errno value on failure. + * + ****************************************************************************/ + +static int imxrt_determine_phy(struct imxrt_driver_s *priv) +{ + uint16_t phydata = 0xffff; + uint8_t phyaddr = 0; + uint8_t last_phyaddr = 0; + int retries; + int ret; + + for (priv->current_phy = 0; priv->current_phy < nitems(g_board_phys); + priv->current_phy++) + { + priv->current_phy_address = + (uint8_t) g_board_phys[priv->current_phy].address_lo; + last_phyaddr = g_board_phys[priv->current_phy].address_high == 0xffff ? + priv->current_phy_address : + (uint8_t) g_board_phys[priv->current_phy].address_high; + + for (phyaddr = priv->current_phy_address; phyaddr <= last_phyaddr; + phyaddr++) + { + retries = 0; + do + { + nxsig_usleep(100); + phydata = 0xffff; + ret = imxrt_readmii(priv, phyaddr, MII_PHYID1, &phydata); + } + while ((ret < 0 || phydata == 0xffff) && ++retries < 3); + + if (retries <= 3 && ret == 0 && + phydata == g_board_phys[priv->current_phy].id1) + { + do + { + nxsig_usleep(100); + phydata = 0xffff; + ret = imxrt_readmii(priv, phyaddr, MII_PHYID2, &phydata); + } + while ((ret < 0 || phydata == 0xffff) && ++retries < 3); + if (retries <= 3 && ret == 0 && + (phydata & 0xfff0) == + (g_board_phys[priv->current_phy].id2 & 0xfff0)) + { + return OK; + } + } + } + } + + return -ENOENT; +} + +/**************************************************************************** + * Function: imxrt_phy_is + * + * Description: + * Compares the name with the current selected PHY's name + * + * Input Parameters: + * priv - Reference to the private ENET driver state structure + * name - a pointer to comapre to. + * + * Returned Value: + * 1 on match, a 0 on no match. + * + ****************************************************************************/ + +static int imxrt_phy_is(struct imxrt_driver_s *priv, const char *name) +{ + return strcmp(g_board_phys[priv->current_phy].name, name) == 0; +} + +/**************************************************************************** + * Function: imxrt_phy_status + * + * Description: + * Compares the name with the current selected PHY's name. + * + * Input Parameters: + * priv - Reference to the private ENET driver state structure + * phydata - last read phy data - may be ignored if there is no + * status register defined by the current PHY. + * mask - A value to and with phydata if a status register is + * defined. Or the value retunred if no status register is + * defined. + * + * Returned Value: + * mask or (phydat & mask) + * + ****************************************************************************/ + +static int imxrt_phy_status(struct imxrt_driver_s *priv, int phydata, + uint16_t mask) +{ + int rv = mask; + if (g_board_phys[priv->current_phy].status != 0xffff) + { + rv &= phydata; + } + + return rv; +} +#endif + #if 0 #if defined(CLAUSE45) /**************************************************************************** @@ -2416,213 +2602,265 @@ static inline int imxrt_initphy(struct imxrt_driver_s *priv, bool renogphy) return -ENXIO; } -#ifdef CONFIG_ETH0_PHY_KSZ8081 - /* Reset PHY */ +#if defined(CONFIG_ETH0_PHY_KSZ8081) || defined(CONFIG_ETH0_PHY_MULTI) +# if defined(CONFIG_ETH0_PHY_MULTI) + if (imxrt_phy_is(priv, MII_KSZ8081_NAME)) + { +# endif + /* Reset PHY */ - imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); + imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); - /* Set RMII mode */ + /* Set RMII mode */ - ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata); - if (ret < 0) - { - nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n"); - return ret; - } + ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata); + if (ret < 0) + { + nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n"); + return ret; + } - /* Indicate 50MHz clock */ + /* Indicate 50MHz clock */ - imxrt_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, - (phydata | (1 << 7))); + imxrt_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, + (phydata | (1 << 7))); - /* Switch off NAND Tree mode (in case it was set via pinning) */ + /* Switch off NAND Tree mode (in case it was set via pinning) */ - ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_OMSO, &phydata); - if (ret < 0) - { - nerr("ERROR: Failed to read MII_KSZ8081_OMSO: %d\n", ret); - return ret; - } + ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_OMSO, &phydata); + if (ret < 0) + { + nerr("ERROR: Failed to read MII_KSZ8081_OMSO: %d\n", ret); + return ret; + } - imxrt_writemii(priv, phyaddr, MII_KSZ8081_OMSO, - (phydata & ~(1 << 5))); + imxrt_writemii(priv, phyaddr, MII_KSZ8081_OMSO, + (phydata & ~(1 << 5))); - /* Set Ethernet led to green = activity and yellow = link and */ + /* Set Ethernet led to green = activity and yellow = link and */ - ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata); - if (ret < 0) - { - nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n"); - return ret; + ret = imxrt_readmii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, &phydata); + if (ret < 0) + { + nerr("ERROR: Failed to read MII_KSZ8081_PHYCTRL2\n"); + return ret; + } + + imxrt_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, + (phydata | (1 << 4))); + + imxrt_writemii(priv, phyaddr, MII_ADVERTISE, + MII_ADVERTISE_100BASETXFULL | + MII_ADVERTISE_100BASETXHALF | + MII_ADVERTISE_10BASETXFULL | + MII_ADVERTISE_10BASETXHALF | + MII_ADVERTISE_CSMA); +# if defined(CONFIG_ETH0_PHY_MULTI) } - imxrt_writemii(priv, phyaddr, MII_KSZ8081_PHYCTRL2, - (phydata | (1 << 4))); +# endif +#endif +#if defined (CONFIG_ETH0_PHY_LAN8720) || \ + defined (CONFIG_ETH0_PHY_LAN8742A) || \ + defined (CONFIG_ETH0_PHY_MULTI) - imxrt_writemii(priv, phyaddr, MII_ADVERTISE, - MII_ADVERTISE_100BASETXFULL | - MII_ADVERTISE_100BASETXHALF | - MII_ADVERTISE_10BASETXFULL | - MII_ADVERTISE_10BASETXHALF | - MII_ADVERTISE_CSMA); +# if defined(CONFIG_ETH0_PHY_MULTI) + if (imxrt_phy_is(priv, MII_LAN8720_NAME) || + imxrt_phy_is(priv, MII_LAN8742A_NAME)) + { +# endif -#elif defined (CONFIG_ETH0_PHY_LAN8720) || defined (CONFIG_ETH0_PHY_LAN8742A) - /* Make sure that PHY comes up in correct mode when it's reset */ + /* Make sure that PHY comes up in correct mode when it's reset */ - imxrt_writemii(priv, phyaddr, MII_LAN8720_MODES, - MII_LAN8720_MODES_RESV | MII_LAN8720_MODES_ALL | - MII_LAN8720_MODES_PHYAD(BOARD_PHY_ADDR)); + imxrt_writemii(priv, phyaddr, MII_LAN8720_MODES, + MII_LAN8720_MODES_RESV | MII_LAN8720_MODES_ALL | + MII_LAN8720_MODES_PHYAD(BOARD_PHY_ADDR)); - /* ...and reset PHY */ + /* ...and reset PHY */ - imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); + imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); -#elif defined (CONFIG_ETH0_PHY_DP83825I) +# if defined(CONFIG_ETH0_PHY_MULTI) + } +# endif +#endif +#if defined (CONFIG_ETH0_PHY_DP83825I) || defined (CONFIG_ETH0_PHY_MULTI) - /* Reset PHY */ +#if defined(CONFIG_ETH0_PHY_MULTI) + if (imxrt_phy_is(priv, MII_DP83825I_NAME)) + { +#endif - imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); + /* Reset PHY */ - /* Set RMII mode and Indicate 50MHz clock */ + imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); - imxrt_writemii(priv, phyaddr, MII_DP83825I_RCSR, - MII_DP83825I_RCSC_ELAST_2 | MII_DP83825I_RCSC_RMIICS); + /* Set RMII mode and Indicate 50MHz clock */ - imxrt_writemii(priv, phyaddr, MII_ADVERTISE, - MII_ADVERTISE_100BASETXFULL | - MII_ADVERTISE_100BASETXHALF | - MII_ADVERTISE_10BASETXFULL | - MII_ADVERTISE_10BASETXHALF | - MII_ADVERTISE_CSMA); + imxrt_writemii(priv, phyaddr, MII_DP83825I_RCSR, + MII_DP83825I_RCSC_ELAST_2 | + MII_DP83825I_RCSC_RMIICS); -#elif defined (CONFIG_ETH0_PHY_YT8512) + imxrt_writemii(priv, phyaddr, MII_ADVERTISE, + MII_ADVERTISE_100BASETXFULL | + MII_ADVERTISE_100BASETXHALF | + MII_ADVERTISE_10BASETXFULL | + MII_ADVERTISE_10BASETXHALF | + MII_ADVERTISE_CSMA); - /* Reset PHY */ +# if defined(CONFIG_ETH0_PHY_MULTI) + } +# endif +#endif - imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); +#if defined(CONFIG_ETH0_PHY_YT8512) || defined(CONFIG_ETH0_PHY_MULTI) +# if defined(CONFIG_ETH0_PHY_MULTI) + if (!imxrt_phy_is(priv, MII_YT8512_NAME)) + { +# endif + /* Reset PHY */ + + imxrt_writemii(priv, phyaddr, MII_MCR, MII_MCR_RESET); - /* Config LEDs */ + /* Config LEDs */ - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, - MII_YT8512_LED0); + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, + MII_YT8512_LED0); - imxrt_readmii(priv, phyaddr, MII_YT8512_DEBUG_DATA, &phydata); + imxrt_readmii(priv, phyaddr, MII_YT8512_DEBUG_DATA, &phydata); - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, - MII_YT8512_LED0); + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, + MII_YT8512_LED0); - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_DATA, 0x331); + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_DATA, 0x331); - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, - MII_YT8512_LED1); + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, + MII_YT8512_LED1); - imxrt_readmii(priv, phyaddr, MII_YT8512_DEBUG_DATA, &phydata); + imxrt_readmii(priv, phyaddr, MII_YT8512_DEBUG_DATA, &phydata); - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, - MII_YT8512_LED1); + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_ADDR_OFFSET, + MII_YT8512_LED1); - imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_DATA, 0x30); + imxrt_writemii(priv, phyaddr, MII_YT8512_DEBUG_DATA, 0x30); - /* Set negotiation */ + /* Set negotiation */ - imxrt_writemii(priv, phyaddr, MII_ADVERTISE, - MII_ADVERTISE_100BASETXFULL | - MII_ADVERTISE_100BASETXHALF | - MII_ADVERTISE_10BASETXFULL | - MII_ADVERTISE_10BASETXHALF | - MII_ADVERTISE_CSMA); + imxrt_writemii(priv, phyaddr, MII_ADVERTISE, + MII_ADVERTISE_100BASETXFULL | + MII_ADVERTISE_100BASETXHALF | + MII_ADVERTISE_10BASETXFULL | + MII_ADVERTISE_10BASETXHALF | + MII_ADVERTISE_CSMA); +# if defined(CONFIG_ETH0_PHY_MULTI) + } +# endif #endif -#if !defined(CONFIG_ETH0_PHY_TJA1103) - /* Start auto negotiation */ +#if !defined(CONFIG_ETH0_PHY_TJA1103) +#if defined(CONFIG_ETH0_PHY_MULTI) + if (!imxrt_phy_is(priv, MII_TJA1103_NAME)) + { +#endif + /* Start auto negotiation */ - ninfo("%s: Start Autonegotiation...\n", BOARD_PHY_NAME); - imxrt_writemii(priv, phyaddr, MII_MCR, - (MII_MCR_ANRESTART | MII_MCR_ANENABLE)); + ninfo("%s: Start Autonegotiation...\n", BOARD_PHY_NAME); + imxrt_writemii(priv, phyaddr, MII_MCR, + (MII_MCR_ANRESTART | MII_MCR_ANENABLE)); - /* Wait for auto negotiation to complete */ + /* Wait for auto negotiation to complete */ - for (retries = 0; retries < LINK_NLOOPS; retries++) - { - ret = imxrt_readmii(priv, phyaddr, MII_MSR, &phydata); - if (ret < 0) + for (retries = 0; retries < LINK_NLOOPS; retries++) { - nerr("ERROR: Failed to read %s MII_MSR: %d\n", - BOARD_PHY_NAME, ret); - return ret; + ret = imxrt_readmii(priv, phyaddr, MII_MSR, &phydata); + if (ret < 0) + { + nerr("ERROR: Failed to read %s MII_MSR: %d\n", + BOARD_PHY_NAME, ret); + return ret; + } + + if (phydata & MII_MSR_ANEGCOMPLETE) + { + break; + } + + nxsig_usleep(LINK_WAITUS); } if (phydata & MII_MSR_ANEGCOMPLETE) { - break; + ninfo("%s: Autonegotiation complete\n", BOARD_PHY_NAME); + ninfo("%s: MII_MSR: %04x\n", BOARD_PHY_NAME, phydata); } + else + { + /* TODO: Autonegotiation has right now failed. Maybe the Eth + * cable is not connected. PHY chip have mechanisms to + * configure link OK. We should leave autconf on, and find a + * way to re-configure MCU whenever the link is ready. + */ - nxsig_usleep(LINK_WAITUS); - } - - if (phydata & MII_MSR_ANEGCOMPLETE) - { - ninfo("%s: Autonegotiation complete\n", BOARD_PHY_NAME); - ninfo("%s: MII_MSR: %04x\n", BOARD_PHY_NAME, phydata); - } - else - { - /* TODO: Autonegotiation has right now failed. Maybe the Eth cable - * is not connected. PHY chip have mechanisms to configure link - * OK. We should leave autconf on, and find a way to re-configure - * MCU whenever the link is ready. - */ - - ninfo("%s: Autonegotiation failed [%d] (is cable plugged-in ?), " - "default to 10Mbs mode\n", \ - BOARD_PHY_NAME, retries); + ninfo("%s: Autonegotiation failed [%d] (is cable plugged-in ?)" + ", default to 10Mbs mode\n", + BOARD_PHY_NAME, retries); - /* Stop auto negotiation */ + /* Stop auto negotiation */ - imxrt_writemii(priv, phyaddr, MII_MCR, 0); + imxrt_writemii(priv, phyaddr, MII_MCR, 0); + } +# if defined(CONFIG_ETH0_PHY_MULTI) } +# endif #endif } #if !defined(CONFIG_ETH0_PHY_TJA1103) - /* When we get here we have a (negotiated) speed and duplex. This is also - * the point we enter if renegotiation is turned off, so have multiple - * attempts at reading the status register in case the PHY isn't awake - * properly. - */ - - retries = 0; - do +# if defined(CONFIG_ETH0_PHY_MULTI) + if (!imxrt_phy_is(priv, MII_TJA1103_NAME)) { - phydata = 0xffff; - ret = imxrt_readmii(priv, phyaddr, BOARD_PHY_STATUS, &phydata); - } - while ((ret < 0 || phydata == 0xffff) && ++retries < 3); - - /* If we didn't successfully read anything and we haven't tried a physical - * renegotiation then lets do that - */ +# endif + /* When we get here we have a (negotiated) speed and duplex. This + * is also the point we enter if renegotiation is turned off, so have + * multiple attempts at reading the status register in case the PHY + * isn't awake properly. + */ - if (retries >= 3) - { - if (renogphy == false) + retries = 0; + do { - /* Give things one more chance with renegotiation turned on */ - - return imxrt_initphy(priv, true); + phydata = 0xffff; + ret = imxrt_readmii(priv, phyaddr, BOARD_PHY_STATUS, &phydata); } - else + while ((ret < 0 || phydata == 0xffff) && ++retries < 3); + + /* If we didn't successfully read anything and we haven't tried + * a physical renegotiation then lets do that + */ + + if (retries >= 3) { - /* That didn't end well, just give up */ + if (renogphy == false) + { + /* Give things one more chance with renegotiation turned on */ - nerr("ERROR: Failed to read %s BOARD_PHY_STATUS[%02x]: %d\n", - BOARD_PHY_NAME, BOARD_PHY_STATUS, ret); - return ret; + return imxrt_initphy(priv, true); + } + else + { + /* That didn't end well, just give up */ + + nerr("ERROR: Failed to read %s BOARD_PHY_STATUS[%02x]: %d\n", + BOARD_PHY_NAME, BOARD_PHY_STATUS, ret); + return ret; + } } - } - ninfo("%s: BOARD_PHY_STATUS: %04x\n", BOARD_PHY_NAME, phydata); + ninfo("%s: BOARD_PHY_STATUS: %04x\n", BOARD_PHY_NAME, phydata); +# if defined(CONFIG_ETH0_PHY_MULTI) + } +# endif #endif /* Set up the transmit and receive control registers based on the diff --git a/arch/arm/src/imxrt/imxrt_start.c b/arch/arm/src/imxrt/imxrt_start.c index cc51d70e4ebac..107e03dae1879 100644 --- a/arch/arm/src/imxrt/imxrt_start.c +++ b/arch/arm/src/imxrt/imxrt_start.c @@ -149,11 +149,16 @@ void __start(void) const register uint32_t *src; register uint32_t *dest; - /* Make sure that interrupts are disabled and set SP */ + /* Make sure that interrupts are disabled and set MSP */ __asm__ __volatile__ ("\tcpsid i\n"); __asm__ __volatile__ ("MSR MSP, %0\n" : : "r" (IDLE_STACK) :); + /* Make sure that we use MSP from now on */ + + __asm__ __volatile__ ("MSR CONTROL, %0\n" : : "r" (0) :); + __asm__ __volatile__ ("ISB SY\n"); + /* Make sure VECTAB is set to NuttX vector table * and not the one from the boot ROM and have consistency * with debugger that automatically set the VECTAB diff --git a/arch/arm/src/stm32f7/stm32_ethernet.c b/arch/arm/src/stm32f7/stm32_ethernet.c index 9771561a20d9d..c4ba77579a0e2 100644 --- a/arch/arm/src/stm32f7/stm32_ethernet.c +++ b/arch/arm/src/stm32f7/stm32_ethernet.c @@ -3132,7 +3132,9 @@ static inline int stm32_dm9161(struct stm32_ethmac_s *priv) static int stm32_phyinit(struct stm32_ethmac_s *priv) { +#ifdef CONFIG_STM32F7_AUTONEG volatile uint32_t timeout; +#endif uint32_t regval; uint16_t phyval; int ret; diff --git a/arch/arm/src/stm32f7/stm32_foc.c b/arch/arm/src/stm32f7/stm32_foc.c index f644bd370ead1..0e6cdfa0ae93a 100644 --- a/arch/arm/src/stm32f7/stm32_foc.c +++ b/arch/arm/src/stm32f7/stm32_foc.c @@ -718,6 +718,7 @@ static struct foc_lower_ops_s g_stm32_foc_ops = .start = stm32_foc_start, .pwm_duty_set = stm32_foc_pwm_duty_set, .pwm_off = stm32_foc_pwm_off, + .info_get = stm32_foc_info_get, .ioctl = stm32_foc_ioctl, .bind = stm32_foc_bind, .fault_clear = stm32_foc_fault_clear, diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index a37e03aa694ba..37b632f9aeb47 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -91,6 +91,14 @@ config ARCH_CHIP_IMX8 ---help--- NXP i.MX8 (ARMv8a) applications processors +config ARCH_CHIP_IMX9 + bool "NXP i.MX9 Platform (ARMv8.2a)" + select ARCH_HAVE_ADDRENV + select ARCH_HAVE_IRQTRIGGER + select ARCH_NEED_ADDRENV_MAPPING + ---help--- + NXP i.MX9 (ARMv8.2a) applications processors + config ARCH_CHIP_ARM64_CUSTOM bool "Custom ARM64 chip" select ARCH_CHIP_CUSTOM @@ -181,6 +189,18 @@ config ARCH_CORTEX_A53 select ARCH_HAVE_TESTSET select ARM_HAVE_NEON +config ARCH_CORTEX_A55 + bool + default n + select ARCH_ARMV8A + select ARCH_HAVE_TRUSTZONE + select ARCH_DCACHE + select ARCH_ICACHE + select ARCH_HAVE_MMU + select ARCH_HAVE_FPU + select ARCH_HAVE_TESTSET + select ARM_HAVE_NEON + config ARCH_CORTEX_A57 bool default n @@ -229,6 +249,7 @@ config ARCH_CHIP default "goldfish" if ARCH_CHIP_GOLDFISH default "fvp-v8r" if ARCH_CHIP_FVP_ARMV8R default "imx8" if ARCH_CHIP_IMX8 + default "imx9" if ARCH_CHIP_IMX9 config ARM_HAVE_NEON bool @@ -311,6 +332,10 @@ if ARCH_CHIP_IMX8 source "arch/arm64/src/imx8/Kconfig" endif +if ARCH_CHIP_IMX9 +source "arch/arm64/src/imx9/Kconfig" +endif + if ARCH_CHIP_GOLDFISH source "arch/arm64/src/goldfish/Kconfig" endif diff --git a/arch/arm64/include/imx9/chip.h b/arch/arm64/include/imx9/chip.h new file mode 100644 index 0000000000000..28553a96e2837 --- /dev/null +++ b/arch/arm64/include/imx9/chip.h @@ -0,0 +1,79 @@ +/**************************************************************************** + * arch/arm64/include/imx9/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_INCLUDE_IMX9_CHIP_H +#define __ARCH_ARM64_INCLUDE_IMX9_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Number of bytes in x kibibytes/mebibytes/gibibytes */ + +#define KB(x) ((x) << 10) +#define MB(x) (KB(x) << 10) +#define GB(x) (MB(UINT64_C(x)) << 10) + +#if defined(CONFIG_ARCH_CHIP_IMX93) + +#if CONFIG_ARM_GIC_VERSION == 3 || CONFIG_ARM_GIC_VERSION == 4 + +#define CONFIG_GICD_BASE 0x48000000 +#define CONFIG_GICR_BASE 0x48040000 +#define CONFIG_GICR_OFFSET 0x20000 + +#else + +#error CONFIG_ARM_GIC_VERSION should be 2, 3 or 4 + +#endif /* CONFIG_ARM_GIC_VERSION */ + +#define CONFIG_RAMBANK1_ADDR 0x80000000 +#define CONFIG_RAMBANK1_SIZE MB(128) + +#define CONFIG_DEVICEIO_BASEADDR 0x40000000 +#define CONFIG_DEVICEIO_SIZE MB(512) + +#define MPID_TO_CLUSTER_ID(mpid) ((mpid) & ~0xff) + +#define IMX9_GPIO_NPORTS 4 + +#endif + +/**************************************************************************** + * Assembly Macros + ****************************************************************************/ + +#ifdef __ASSEMBLY__ + +.macro get_cpu_id xreg0 + mrs \xreg0, mpidr_el1 + ubfx \xreg0, \xreg0, #0, #8 +.endm + +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM64_INCLUDE_IMX9_CHIP_H */ diff --git a/arch/arm64/include/imx9/imx93_irq.h b/arch/arm64/include/imx9/imx93_irq.h new file mode 100644 index 0000000000000..5e5de4ba43709 --- /dev/null +++ b/arch/arm64/include/imx9/imx93_irq.h @@ -0,0 +1,298 @@ +/**************************************************************************** + * arch/arm64/include/imx9/imx93_irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_INCLUDE_IMX9_IMX93_IRQ_H +#define __ARCH_ARM64_INCLUDE_IMX9_IMX93_IRQ_H + +#define IMX9_IRQ_RESERVED32 (IMX9_IRQ_EXT + 0) /* Exception condition notification while boot */ +#define IMX9_IRQ_RESERVED33 (IMX9_IRQ_EXT + 1) /* DAP interrupt */ +#define IMX9_IRQ_RESERVED34 (IMX9_IRQ_EXT + 2) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED35 (IMX9_IRQ_EXT + 3) /* CTI trigger outputs from CM33 platform */ +#define IMX9_IRQ_RESERVED36 (IMX9_IRQ_EXT + 4) /* CTI trigger outputs from CA55 platform */ +#define IMX9_IRQ_RESERVED37 (IMX9_IRQ_EXT + 5) /* Performance Unit Interrupts from CA55 platform */ +#define IMX9_IRQ_RESERVED38 (IMX9_IRQ_EXT + 6) /* ECC error from CA55 platform cache */ +#define IMX9_IRQ_RESERVED39 (IMX9_IRQ_EXT + 7) /* 1-bit or 2-bit ECC or Parity error from CA55 platform cache */ +#define IMX9_IRQ_CAN1 (IMX9_IRQ_EXT + 8) /* CAN1 interrupt */ +#define IMX9_IRQ_CAN1_ERROR (IMX9_IRQ_EXT + 9) /* CAN1 error interrupt */ +#define IMX9_IRQ_GPIO1_0_15 (IMX9_IRQ_EXT + 10) /* General Purpose Input/Output 1 interrupt 0 */ +#define IMX9_IRQ_GPIO1_16_31 (IMX9_IRQ_EXT + 11) /* General Purpose Input/Output 1 interrupt 1 */ +#define IMX9_IRQ_I3C1 (IMX9_IRQ_EXT + 12) /* Improved Inter-Integrated Circuit 1 interrupt */ +#define IMX9_IRQ_LPI2C1 (IMX9_IRQ_EXT + 13) /* Low Power Inter-Integrated Circuit module 1 */ +#define IMX9_IRQ_LPI2C2 (IMX9_IRQ_EXT + 14) /* Low Power Inter-Integrated Circuit module 2 */ +#define IMX9_IRQ_LPIT1 (IMX9_IRQ_EXT + 15) /* Low Power Periodic Interrupt Timer 1 */ +#define IMX9_IRQ_LPSPI1 (IMX9_IRQ_EXT + 16) /* Low Power Serial Peripheral Interface 1 */ +#define IMX9_IRQ_LPSPI2 (IMX9_IRQ_EXT + 17) /* Low Power Serial Peripheral Interface 2 */ +#define IMX9_IRQ_LPTMR1 (IMX9_IRQ_EXT + 18) /* Low Power Timer 1 */ +#define IMX9_IRQ_LPUART1 (IMX9_IRQ_EXT + 19) /* Low Power UART 1 */ +#define IMX9_IRQ_LPUART2 (IMX9_IRQ_EXT + 20) /* Low Power UART 2 */ +#define IMX9_IRQ_MU1_A (IMX9_IRQ_EXT + 21) /* Messaging Unit 1 - Side A (to communicate with M7 core) */ +#define IMX9_IRQ_MU1_B (IMX9_IRQ_EXT + 22) /* Messaging Unit 1 - Side B (to communicate with M33 core) */ +#define IMX9_IRQ_MU2_A (IMX9_IRQ_EXT + 23) /* Messaging Unit 2 - Side A (to communicate with M7 core) */ +#define IMX9_IRQ_MU2_B (IMX9_IRQ_EXT + 24) /* Messaging Unit 2 - Side B (to communicate with A55 core) */ +#define IMX9_IRQ_RESERVED57 (IMX9_IRQ_EXT + 25) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED58 (IMX9_IRQ_EXT + 26) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED59 (IMX9_IRQ_EXT + 27) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED60 (IMX9_IRQ_EXT + 28) /* Edgelock Trust MUA RX full interrupt */ +#define IMX9_IRQ_RESERVED61 (IMX9_IRQ_EXT + 29) /* Edgelock Trust MUA TX empty interrupt */ +#define IMX9_IRQ_RESERVED62 (IMX9_IRQ_EXT + 30) /* Edgelock Apps Core MUA RX full interrupt */ +#define IMX9_IRQ_RESERVED63 (IMX9_IRQ_EXT + 31) /* Edgelock Apps Core MUA TX empty interrupt */ +#define IMX9_IRQ_RESERVED64 (IMX9_IRQ_EXT + 32) /* Edgelock Realtime Core MUA RX full interrupt */ +#define IMX9_IRQ_RESERVED65 (IMX9_IRQ_EXT + 33) /* Edgelock Realtime Core MUA TX empty interrupt */ +#define IMX9_IRQ_RESERVED66 (IMX9_IRQ_EXT + 34) /* Edgelock secure interrupt */ +#define IMX9_IRQ_RESERVED67 (IMX9_IRQ_EXT + 35) /* Edgelock non-secure interrupt */ +#define IMX9_IRQ_TPM1 (IMX9_IRQ_EXT + 36) /* Timer PWM module 1 */ +#define IMX9_IRQ_TPM2 (IMX9_IRQ_EXT + 37) /* Timer PWM module 2 */ +#define IMX9_IRQ_WDOG1 (IMX9_IRQ_EXT + 38) /* Watchdog 1 Interrupt */ +#define IMX9_IRQ_WDOG2 (IMX9_IRQ_EXT + 39) /* Watchdog 2 Interrupt */ +#define IMX9_IRQ_TRDC (IMX9_IRQ_EXT + 40) /* AONMIX TRDC transfer error interrupt */ +#define IMX9_IRQ_RESERVED73 (IMX9_IRQ_EXT + 41) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED74 (IMX9_IRQ_EXT + 42) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED75 (IMX9_IRQ_EXT + 43) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED76 (IMX9_IRQ_EXT + 44) /* Reserved interrupt */ +#define IMX9_IRQ_SAI1 (IMX9_IRQ_EXT + 45) /* Serial Audio Interface 1 */ +#define IMX9_IRQ_RESERVED78 (IMX9_IRQ_EXT + 46) /* M33 PS Tag/Data Parity Error */ +#define IMX9_IRQ_RESERVED79 (IMX9_IRQ_EXT + 47) /* M33 TCM ECC interrupt */ +#define IMX9_IRQ_RESERVED80 (IMX9_IRQ_EXT + 48) /* M33 TCM Error interrupt */ +#define IMX9_IRQ_RESERVED81 (IMX9_IRQ_EXT + 49) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED82 (IMX9_IRQ_EXT + 50) /* Reserved interrupt */ +#define IMX9_IRQ_CAN2 (IMX9_IRQ_EXT + 51) /* CAN2 interrupt */ +#define IMX9_IRQ_CAN2_ERROR (IMX9_IRQ_EXT + 52) /* CAN2 error interrupt */ +#define IMX9_IRQ_FLEXIO1 (IMX9_IRQ_EXT + 53) /* Flexible IO 1 interrupt */ +#define IMX9_IRQ_FLEXIO2 (IMX9_IRQ_EXT + 54) /* Flexible IO 2 interrupt */ +#define IMX9_IRQ_FLEXSPI1 (IMX9_IRQ_EXT + 55) /* FlexSPI controller interface interrupt 1 */ +#define IMX9_IRQ_RESERVED88 (IMX9_IRQ_EXT + 56) /* Reserved interrupt */ +#define IMX9_IRQ_GPIO2_0_15 (IMX9_IRQ_EXT + 57) /* General Purpose Input/Output 2 interrupt 0 */ +#define IMX9_IRQ_GPIO2_16_31 (IMX9_IRQ_EXT + 58) /* General Purpose Input/Output 2 interrupt 1 */ +#define IMX9_IRQ_GPIO3_0_15 (IMX9_IRQ_EXT + 59) /* General Purpose Input/Output 3 interrupt 0 */ +#define IMX9_IRQ_GPIO3_16_31 (IMX9_IRQ_EXT + 60) /* General Purpose Input/Output 3 interrupt 1 */ +#define IMX9_IRQ_I3C2 (IMX9_IRQ_EXT + 61) /* Improved Inter-Integrated Circuit 2 interrupt */ +#define IMX9_IRQ_LPI2C3 (IMX9_IRQ_EXT + 62) /* Low Power Inter-Integrated Circuit module 3 */ +#define IMX9_IRQ_LPI2C4 (IMX9_IRQ_EXT + 63) /* Low Power Inter-Integrated Circuit module 4 */ +#define IMX9_IRQ_LPIT2 (IMX9_IRQ_EXT + 64) /* Low Power Periodic Interrupt Timer 2 */ +#define IMX9_IRQ_LPSPI3 (IMX9_IRQ_EXT + 65) /* Low Power Serial Peripheral Interface 3 */ +#define IMX9_IRQ_LPSPI4 (IMX9_IRQ_EXT + 66) /* Low Power Serial Peripheral Interface 4 */ +#define IMX9_IRQ_LPTMR2 (IMX9_IRQ_EXT + 67) /* Low Power Timer 2 */ +#define IMX9_IRQ_LPUART3 (IMX9_IRQ_EXT + 68) /* Low Power UART 3 */ +#define IMX9_IRQ_LPUART4 (IMX9_IRQ_EXT + 69) /* Low Power UART 4 */ +#define IMX9_IRQ_LPUART5 (IMX9_IRQ_EXT + 70) /* Low Power UART 5 */ +#define IMX9_IRQ_LPUART6 (IMX9_IRQ_EXT + 71) /* Low Power UART 6 */ +#define IMX9_IRQ_RESERVED104 (IMX9_IRQ_EXT + 72) /* MTR Master error interrupt */ +#define IMX9_IRQ_RESERVED105 (IMX9_IRQ_EXT + 73) /* BBNSM Non-Secure interrupt */ +#define IMX9_IRQ_RESERVED106 (IMX9_IRQ_EXT + 74) /* System Counter compare interrupt */ +#define IMX9_IRQ_TPM3 (IMX9_IRQ_EXT + 75) /* Timer PWM module 3 */ +#define IMX9_IRQ_TPM4 (IMX9_IRQ_EXT + 76) /* Timer PWM module 4 */ +#define IMX9_IRQ_TPM5 (IMX9_IRQ_EXT + 77) /* Timer PWM module 5 */ +#define IMX9_IRQ_TPM6 (IMX9_IRQ_EXT + 78) /* Timer PWM module 6 */ +#define IMX9_IRQ_WDOG3 (IMX9_IRQ_EXT + 79) /* Watchdog 3 Interrupt */ +#define IMX9_IRQ_WDOG4 (IMX9_IRQ_EXT + 80) /* Watchdog 4 Interrupt */ +#define IMX9_IRQ_WDOG5 (IMX9_IRQ_EXT + 81) /* Watchdog 5 Interrupt */ +#define IMX9_IRQ_RESERVED114 (IMX9_IRQ_EXT + 82) /* WAKEUPMIX TRDC transfer error interrupt */ +#define IMX9_IRQ_TEMPMON (IMX9_IRQ_EXT + 83) /* TempSensor interrupt */ +#define IMX9_IRQ_RESERVED116 (IMX9_IRQ_EXT + 84) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED117 (IMX9_IRQ_EXT + 85) /* Reserved interrupt */ +#define IMX9_IRQ_USDHC1 (IMX9_IRQ_EXT + 86) /* ultra Secure Digital Host Controller interrupt 1 */ +#define IMX9_IRQ_USDHC2 (IMX9_IRQ_EXT + 87) /* ultra Secure Digital Host Controller interrupt 2 */ +#define IMX9_IRQ_RESERVED120 (IMX9_IRQ_EXT + 88) /* MEGAMIX TRDC transfer error interrupt */ +#define IMX9_IRQ_RESERVED121 (IMX9_IRQ_EXT + 89) /* NIC_WRAPPER TRDC transfer error interrupt */ +#define IMX9_IRQ_RESERVED122 (IMX9_IRQ_EXT + 90) /* DRAM controller Performance Monitor Interrupt */ +#define IMX9_IRQ_RESERVED123 (IMX9_IRQ_EXT + 91) /* DRAM controller Critical Interrupt */ +#define IMX9_IRQ_RESERVED124 (IMX9_IRQ_EXT + 92) /* DRAM Phy Critical Interrupt */ +#define IMX9_IRQ_RESERVED125 (IMX9_IRQ_EXT + 93) /* Reserved interrupt */ +#define IMX9_IRQ_DMA3_ERROR (IMX9_IRQ_EXT + 94) /* eDMA1 error interrupt */ +#define IMX9_IRQ_DMA3_0 (IMX9_IRQ_EXT + 95) /* eDMA1 channel 0 interrupt */ +#define IMX9_IRQ_DMA3_1 (IMX9_IRQ_EXT + 96) /* eDMA1 channel 1 interrupt */ +#define IMX9_IRQ_DMA3_2 (IMX9_IRQ_EXT + 97) /* eDMA1 channel 2 interrupt */ +#define IMX9_IRQ_DMA3_3 (IMX9_IRQ_EXT + 98) /* eDMA1 channel 3 interrupt */ +#define IMX9_IRQ_DMA3_4 (IMX9_IRQ_EXT + 99) /* eDMA1 channel 4 interrupt */ +#define IMX9_IRQ_DMA3_5 (IMX9_IRQ_EXT + 100) /* eDMA1 channel 5 interrupt */ +#define IMX9_IRQ_DMA3_6 (IMX9_IRQ_EXT + 101) /* eDMA1 channel 6 interrupt */ +#define IMX9_IRQ_DMA3_7 (IMX9_IRQ_EXT + 102) /* eDMA1 channel 7 interrupt */ +#define IMX9_IRQ_DMA3_8 (IMX9_IRQ_EXT + 103) /* eDMA1 channel 8 interrupt */ +#define IMX9_IRQ_DMA3_9 (IMX9_IRQ_EXT + 104) /* eDMA1 channel 9 interrupt */ +#define IMX9_IRQ_DMA3_10 (IMX9_IRQ_EXT + 105) /* eDMA1 channel 10 interrupt */ +#define IMX9_IRQ_DMA3_11 (IMX9_IRQ_EXT + 106) /* eDMA1 channel 11 interrupt */ +#define IMX9_IRQ_DMA3_12 (IMX9_IRQ_EXT + 107) /* eDMA1 channel 12 interrupt */ +#define IMX9_IRQ_DMA3_13 (IMX9_IRQ_EXT + 108) /* eDMA1 channel 13 interrupt */ +#define IMX9_IRQ_DMA3_14 (IMX9_IRQ_EXT + 109) /* eDMA1 channel 14 interrupt */ +#define IMX9_IRQ_DMA3_15 (IMX9_IRQ_EXT + 110) /* eDMA1 channel 15 interrupt */ +#define IMX9_IRQ_DMA3_16 (IMX9_IRQ_EXT + 111) /* eDMA1 channel 16 interrupt */ +#define IMX9_IRQ_DMA3_17 (IMX9_IRQ_EXT + 112) /* eDMA1 channel 17 interrupt */ +#define IMX9_IRQ_DMA3_18 (IMX9_IRQ_EXT + 113) /* eDMA1 channel 18 interrupt */ +#define IMX9_IRQ_DMA3_19 (IMX9_IRQ_EXT + 114) /* eDMA1 channel 19 interrupt */ +#define IMX9_IRQ_DMA3_20 (IMX9_IRQ_EXT + 115) /* eDMA1 channel 20 interrupt */ +#define IMX9_IRQ_DMA3_21 (IMX9_IRQ_EXT + 116) /* eDMA1 channel 21 interrupt */ +#define IMX9_IRQ_DMA3_22 (IMX9_IRQ_EXT + 117) /* eDMA1 channel 22 interrupt */ +#define IMX9_IRQ_DMA3_23 (IMX9_IRQ_EXT + 118) /* eDMA1 channel 23 interrupt */ +#define IMX9_IRQ_DMA3_24 (IMX9_IRQ_EXT + 119) /* eDMA1 channel 24 interrupt */ +#define IMX9_IRQ_DMA3_25 (IMX9_IRQ_EXT + 120) /* eDMA1 channel 25 interrupt */ +#define IMX9_IRQ_DMA3_26 (IMX9_IRQ_EXT + 121) /* eDMA1 channel 26 interrupt */ +#define IMX9_IRQ_DMA3_27 (IMX9_IRQ_EXT + 122) /* eDMA1 channel 27 interrupt */ +#define IMX9_IRQ_DMA3_28 (IMX9_IRQ_EXT + 123) /* eDMA1 channel 28 interrupt */ +#define IMX9_IRQ_DMA3_29 (IMX9_IRQ_EXT + 124) /* eDMA1 channel 29 interrupt */ +#define IMX9_IRQ_DMA3_30 (IMX9_IRQ_EXT + 125) /* eDMA1 channel 30 interrupt */ +#define IMX9_IRQ_RESERVED158 (IMX9_IRQ_EXT + 126) /* Reserved interrupt */ +#define IMX9_IRQ_DMA4_ERROR (IMX9_IRQ_EXT + 127) /* eDMA2 error interrupt */ +#define IMX9_IRQ_DMA4_0_1 (IMX9_IRQ_EXT + 128) /* eDMA2 channel 0/1 interrupt */ +#define IMX9_IRQ_DMA4_2_3 (IMX9_IRQ_EXT + 129) /* eDMA2 channel 2/3 interrupt */ +#define IMX9_IRQ_DMA4_4_5 (IMX9_IRQ_EXT + 130) /* eDMA2 channel 4/5 interrupt */ +#define IMX9_IRQ_DMA4_6_7 (IMX9_IRQ_EXT + 131) /* eDMA2 channel 6/7 interrupt */ +#define IMX9_IRQ_DMA4_8_9 (IMX9_IRQ_EXT + 132) /* eDMA2 channel 8/9 interrupt */ +#define IMX9_IRQ_DMA4_10_11 (IMX9_IRQ_EXT + 133) /* eDMA2 channel 10/11 interrupt */ +#define IMX9_IRQ_DMA4_12_13 (IMX9_IRQ_EXT + 134) /* eDMA2 channel 12/13 interrupt */ +#define IMX9_IRQ_DMA4_14_15 (IMX9_IRQ_EXT + 135) /* eDMA2 channel 14/15 interrupt */ +#define IMX9_IRQ_DMA4_16_17 (IMX9_IRQ_EXT + 136) /* eDMA2 channel 16/17 interrupt */ +#define IMX9_IRQ_DMA4_18_19 (IMX9_IRQ_EXT + 137) /* eDMA2 channel 18/19 interrupt */ +#define IMX9_IRQ_DMA4_20_21 (IMX9_IRQ_EXT + 138) /* eDMA2 channel 20/21 interrupt */ +#define IMX9_IRQ_DMA4_22_23 (IMX9_IRQ_EXT + 139) /* eDMA2 channel 22/23 interrupt */ +#define IMX9_IRQ_DMA4_24_25 (IMX9_IRQ_EXT + 140) /* eDMA2 channel 24/25 interrupt */ +#define IMX9_IRQ_DMA4_26_27 (IMX9_IRQ_EXT + 141) /* eDMA2 channel 26/27 interrupt */ +#define IMX9_IRQ_DMA4_28_29 (IMX9_IRQ_EXT + 142) /* eDMA2 channel 28/29 interrupt */ +#define IMX9_IRQ_DMA4_30_31 (IMX9_IRQ_EXT + 143) /* eDMA2 channel 30/31 interrupt */ +#define IMX9_IRQ_DMA4_32_33 (IMX9_IRQ_EXT + 144) /* eDMA2 channel 32/33 interrupt */ +#define IMX9_IRQ_DMA4_34_35 (IMX9_IRQ_EXT + 145) /* eDMA2 channel 34/35 interrupt */ +#define IMX9_IRQ_DMA4_36_37 (IMX9_IRQ_EXT + 146) /* eDMA2 channel 36/37 interrupt */ +#define IMX9_IRQ_DMA4_38_39 (IMX9_IRQ_EXT + 147) /* eDMA2 channel 38/39 interrupt */ +#define IMX9_IRQ_DMA4_40_41 (IMX9_IRQ_EXT + 148) /* eDMA2 channel 40/41 interrupt */ +#define IMX9_IRQ_DMA4_42_43 (IMX9_IRQ_EXT + 149) /* eDMA2 channel 42/43 interrupt */ +#define IMX9_IRQ_DMA4_44_45 (IMX9_IRQ_EXT + 150) /* eDMA2 channel 44/45 interrupt */ +#define IMX9_IRQ_DMA4_46_47 (IMX9_IRQ_EXT + 151) /* eDMA2 channel 46/47 interrupt */ +#define IMX9_IRQ_DMA4_48_49 (IMX9_IRQ_EXT + 152) /* eDMA2 channel 48/49 interrupt */ +#define IMX9_IRQ_DMA4_50_51 (IMX9_IRQ_EXT + 153) /* eDMA2 channel 50/51 interrupt */ +#define IMX9_IRQ_DMA4_52_53 (IMX9_IRQ_EXT + 154) /* eDMA2 channel 52/53 interrupt */ +#define IMX9_IRQ_DMA4_54_55 (IMX9_IRQ_EXT + 155) /* eDMA2 channel 54/55 interrupt */ +#define IMX9_IRQ_DMA4_56_57 (IMX9_IRQ_EXT + 156) /* eDMA2 channel 56/57 interrupt */ +#define IMX9_IRQ_DMA4_58_59 (IMX9_IRQ_EXT + 157) /* eDMA2 channel 58/59 interrupt */ +#define IMX9_IRQ_DMA4_60_61 (IMX9_IRQ_EXT + 158) /* eDMA2 channel 60/61 interrupt */ +#define IMX9_IRQ_DMA4_62_63 (IMX9_IRQ_EXT + 159) /* eDMA2 channel 62/63 interrupt */ +#define IMX9_IRQ_RESERVED192 (IMX9_IRQ_EXT + 160) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED193 (IMX9_IRQ_EXT + 161) /* Edgelock Group 1 reset source */ +#define IMX9_IRQ_RESERVED194 (IMX9_IRQ_EXT + 162) /* Edgelock Group 2 reset source */ +#define IMX9_IRQ_RESERVED195 (IMX9_IRQ_EXT + 163) /* Edgelock Group 2 reset source */ +#define IMX9_IRQ_RESERVED196 (IMX9_IRQ_EXT + 164) /* JTAGSW DAP MDM-AP SRC reset source */ +#define IMX9_IRQ_RESERVED197 (IMX9_IRQ_EXT + 165) /* JTAGC SRC reset source */ +#define IMX9_IRQ_RESERVED198 (IMX9_IRQ_EXT + 166) /* CM33 SYSREQRST SRC reset source */ +#define IMX9_IRQ_RESERVED199 (IMX9_IRQ_EXT + 167) /* CM33 LOCKUP SRC reset source */ +#define IMX9_IRQ_RESERVED200 (IMX9_IRQ_EXT + 168) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED201 (IMX9_IRQ_EXT + 169) /* Reserved interrupt */ +#define IMX9_IRQ_SAI2 (IMX9_IRQ_EXT + 170) /* Serial Audio Interface 2 */ +#define IMX9_IRQ_SAI3 (IMX9_IRQ_EXT + 171) /* Serial Audio Interface 3 */ +#define IMX9_IRQ_ISI (IMX9_IRQ_EXT + 172) /* ISI interrupt */ +#define IMX9_IRQ_RESERVED205 (IMX9_IRQ_EXT + 173) /* PXP interrupt 0 */ +#define IMX9_IRQ_RESERVED206 (IMX9_IRQ_EXT + 174) /* PXP interrupt 1 */ +#define IMX9_IRQ_CSI (IMX9_IRQ_EXT + 175) /* CSI interrupt */ +#define IMX9_IRQ_RESERVED208 (IMX9_IRQ_EXT + 176) /* LCDIF Sync Interrupt */ +#define IMX9_IRQ_DSI (IMX9_IRQ_EXT + 177) /* MIPI DSI Interrupt Request */ +#define IMX9_IRQ_RESERVED210 (IMX9_IRQ_EXT + 178) /* Machine learning processor interrupt */ +#define IMX9_IRQ_ENET_MAC0_RX_TX_D ONE1 (IMX9_IRQ_EXT + 179) /* MAC 0 Receive/ Trasmit Frame/ Buffer Done */ +#define IMX9_IRQ_ENET_MAC0_RX_TX_D ONE2 (IMX9_IRQ_EXT + 180) /* MAC 0 Receive/ Trasmit Frame/ Buffer Done */ +#define IMX9_IRQ_ENET (IMX9_IRQ_EXT + 181) /* MAC 0 IRQ */ +#define IMX9_IRQ_ENET_1588 (IMX9_IRQ_EXT + 182) /* MAC 0 1588 Timer Interrupt - synchronous */ +#define IMX9_IRQ_ENET_QOS_PMT (IMX9_IRQ_EXT + 183) /* ENET QOS PMT interrupt */ +#define IMX9_IRQ_ENET_QOS (IMX9_IRQ_EXT + 184) /* ENET QOS interrupt */ +#define IMX9_IRQ_RESERVED217 (IMX9_IRQ_EXT + 185) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED218 (IMX9_IRQ_EXT + 186) /* Reserved interrupt */ +#define IMX9_IRQ_USB1 (IMX9_IRQ_EXT + 187) /* USB-1 Wake-up Interrupt */ +#define IMX9_IRQ_USB2 (IMX9_IRQ_EXT + 188) /* USB-2 Wake-up Interrupt */ +#define IMX9_IRQ_GPIO4_0_15 (IMX9_IRQ_EXT + 189) /* General Purpose Input/Output 4 interrupt 0 */ +#define IMX9_IRQ_GPIO4_16_31 (IMX9_IRQ_EXT + 190) /* General Purpose Input/Output 4 interrupt 1 */ +#define IMX9_IRQ_LPSPI5 (IMX9_IRQ_EXT + 191) /* Low Power Serial Peripheral Interface 5 */ +#define IMX9_IRQ_LPSPI6 (IMX9_IRQ_EXT + 192) /* Low Power Serial Peripheral Interface 6 */ +#define IMX9_IRQ_LPSPI7 (IMX9_IRQ_EXT + 193) /* Low Power Serial Peripheral Interface 7 */ +#define IMX9_IRQ_LPSPI8 (IMX9_IRQ_EXT + 194) /* Low Power Serial Peripheral Interface 8 */ +#define IMX9_IRQ_LPI2C5 (IMX9_IRQ_EXT + 195) /* Low Power Inter-Integrated Circuit module 5 */ +#define IMX9_IRQ_LPI2C6 (IMX9_IRQ_EXT + 196) /* Low Power Inter-Integrated Circuit module 6 */ +#define IMX9_IRQ_LPI2C7 (IMX9_IRQ_EXT + 197) /* Low Power Inter-Integrated Circuit module 7 */ +#define IMX9_IRQ_LPI2C8 (IMX9_IRQ_EXT + 198) /* Low Power Inter-Integrated Circuit module 8 */ +#define IMX9_IRQ_PDM_HWVAD_ERROR (IMX9_IRQ_EXT + 199) /* PDM interrupt */ +#define IMX9_IRQ_PDM_HWVAD_EVENT (IMX9_IRQ_EXT + 200) /* PDM interrupt */ +#define IMX9_IRQ_PDM_ERROR (IMX9_IRQ_EXT + 201) /* PDM interrupt */ +#define IMX9_IRQ_PDM_EVENT (IMX9_IRQ_EXT + 202) /* PDM interrupt */ +#define IMX9_IRQ_RESERVED235 (IMX9_IRQ_EXT + 203) /* AUDIO XCVR interrupt */ +#define IMX9_IRQ_RESERVED236 (IMX9_IRQ_EXT + 204) /* AUDIO XCVR interrupt */ +#define IMX9_IRQ_USDHC3 (IMX9_IRQ_EXT + 205) /* ultra Secure Digital Host Controller interrupt 3 */ +#define IMX9_IRQ_RESERVED238 (IMX9_IRQ_EXT + 206) /* OCRAM MECC interrupt */ +#define IMX9_IRQ_RESERVED239 (IMX9_IRQ_EXT + 207) /* OCRAM MECC interrupt */ +#define IMX9_IRQ_RESERVED240 (IMX9_IRQ_EXT + 208) /* HSIOMIX TRDC transfer error interrupt */ +#define IMX9_IRQ_RESERVED241 (IMX9_IRQ_EXT + 209) /* MEDIAMIX TRDC transfer error interrupt */ +#define IMX9_IRQ_LPUART7 (IMX9_IRQ_EXT + 210) /* Low Power UART 7 */ +#define IMX9_IRQ_LPUART8 (IMX9_IRQ_EXT + 211) /* Low Power UART 8 */ +#define IMX9_IRQ_RESERVED244 (IMX9_IRQ_EXT + 212) /* CM33 MCM interrupt */ +#define IMX9_IRQ_RESERVED245 (IMX9_IRQ_EXT + 213) /* SFA interrupt */ +#define IMX9_IRQ_RESERVED246 (IMX9_IRQ_EXT + 214) /* GIC600 INTERRUPT */ +#define IMX9_IRQ_RESERVED247 (IMX9_IRQ_EXT + 215) /* GIC600 INTERRUPT */ +#define IMX9_IRQ_RESERVED248 (IMX9_IRQ_EXT + 216) /* GIC600 INTERRUPT */ +#define IMX9_IRQ_RESERVED249 (IMX9_IRQ_EXT + 217) /* ADC interrupt */ +#define IMX9_IRQ_RESERVED250 (IMX9_IRQ_EXT + 218) /* ADC interrupt */ +#define IMX9_IRQ_RESERVED251 (IMX9_IRQ_EXT + 219) /* ADC interrupt */ +#define IMX9_IRQ_RESERVED252 (IMX9_IRQ_EXT + 220) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED253 (IMX9_IRQ_EXT + 221) /* I3C1 wakeup irq after double sync */ +#define IMX9_IRQ_RESERVED254 (IMX9_IRQ_EXT + 222) /* I3C2 wakeup irq after double sync */ +#define IMX9_IRQ_RESERVED255 (IMX9_IRQ_EXT + 223) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED256 (IMX9_IRQ_EXT + 224) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED257 (IMX9_IRQ_EXT + 225) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED258 (IMX9_IRQ_EXT + 226) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED259 (IMX9_IRQ_EXT + 227) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED260 (IMX9_IRQ_EXT + 228) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED261 (IMX9_IRQ_EXT + 229) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED262 (IMX9_IRQ_EXT + 230) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED263 (IMX9_IRQ_EXT + 231) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED264 (IMX9_IRQ_EXT + 232) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED265 (IMX9_IRQ_EXT + 233) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED266 (IMX9_IRQ_EXT + 234) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED267 (IMX9_IRQ_EXT + 235) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED268 (IMX9_IRQ_EXT + 236) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED269 (IMX9_IRQ_EXT + 237) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED270 (IMX9_IRQ_EXT + 238) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED271 (IMX9_IRQ_EXT + 239) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED272 (IMX9_IRQ_EXT + 240) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED273 (IMX9_IRQ_EXT + 241) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED274 (IMX9_IRQ_EXT + 242) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED275 (IMX9_IRQ_EXT + 243) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED276 (IMX9_IRQ_EXT + 244) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED277 (IMX9_IRQ_EXT + 245) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED278 (IMX9_IRQ_EXT + 246) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED279 (IMX9_IRQ_EXT + 247) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED280 (IMX9_IRQ_EXT + 248) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED281 (IMX9_IRQ_EXT + 249) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED282 (IMX9_IRQ_EXT + 250) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED283 (IMX9_IRQ_EXT + 251) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED284 (IMX9_IRQ_EXT + 252) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED285 (IMX9_IRQ_EXT + 253) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED286 (IMX9_IRQ_EXT + 254) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED287 (IMX9_IRQ_EXT + 255) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED288 (IMX9_IRQ_EXT + 256) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED289 (IMX9_IRQ_EXT + 257) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED290 (IMX9_IRQ_EXT + 258) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED291 (IMX9_IRQ_EXT + 259) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED292 (IMX9_IRQ_EXT + 260) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED293 (IMX9_IRQ_EXT + 261) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED294 (IMX9_IRQ_EXT + 262) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED295 (IMX9_IRQ_EXT + 263) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED296 (IMX9_IRQ_EXT + 264) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED297 (IMX9_IRQ_EXT + 265) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED298 (IMX9_IRQ_EXT + 266) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED299 (IMX9_IRQ_EXT + 267) /* Reserved interrupt */ +#define IMX9_IRQ_RESERVED300 (IMX9_IRQ_EXT + 268) /* ADC Asynchronous Interrupt */ + +/* Total amount of entries in system vector table */ + +#define NR_IRQS (301) + +#endif /* __ARCH_ARM64_INCLUDE_IMX9_IMX93_IRQ_H */ diff --git a/arch/arm64/include/imx9/irq.h b/arch/arm64/include/imx9/irq.h new file mode 100644 index 0000000000000..5e96f56a7957a --- /dev/null +++ b/arch/arm64/include/imx9/irq.h @@ -0,0 +1,70 @@ +/**************************************************************************** + * arch/arm64/include/imx9/irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM64_INCLUDE_IMX9_IRQ_H +#define __ARCH_ARM64_INCLUDE_IMX9_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_ARCH_CHIP_IMX93) +# include +#else +# error "Unrecognized i.MX9 architecture" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMX9_IRQ_SOFTWARE0 (0) /* Cortex-A55 Software Generated Interrupt 0 */ +#define IMX9_IRQ_SOFTWARE1 (1) /* Cortex-A55 Software Generated Interrupt 1 */ +#define IMX9_IRQ_SOFTWARE2 (2) /* Cortex-A55 Software Generated Interrupt 2 */ +#define IMX9_IRQ_SOFTWARE3 (3) /* Cortex-A55 Software Generated Interrupt 3 */ +#define IMX9_IRQ_SOFTWARE4 (4) /* Cortex-A55 Software Generated Interrupt 4 */ +#define IMX9_IRQ_SOFTWARE5 (5) /* Cortex-A55 Software Generated Interrupt 5 */ +#define IMX9_IRQ_SOFTWARE6 (6) /* Cortex-A55 Software Generated Interrupt 6 */ +#define IMX9_IRQ_SOFTWARE7 (7) /* Cortex-A55 Software Generated Interrupt 7 */ +#define IMX9_IRQ_SOFTWARE8 (8) /* Cortex-A55 Software Generated Interrupt 8 */ +#define IMX9_IRQ_SOFTWARE9 (9) /* Cortex-A55 Software Generated Interrupt 9 */ +#define IMX9_IRQ_SOFTWARE10 (10) /* Cortex-A55 Software Generated Interrupt 10 */ +#define IMX9_IRQ_SOFTWARE11 (11) /* Cortex-A55 Software Generated Interrupt 11 */ +#define IMX9_IRQ_SOFTWARE12 (12) /* Cortex-A55 Software Generated Interrupt 12 */ +#define IMX9_IRQ_SOFTWARE13 (13) /* Cortex-A55 Software Generated Interrupt 13 */ +#define IMX9_IRQ_SOFTWARE14 (14) /* Cortex-A55 Software Generated Interrupt 14 */ +#define IMX9_IRQ_SOFTWARE15 (15) /* Cortex-A55 Software Generated Interrupt 15 */ +#define IMX9_IRQ_VIRTUALMAINTENANCE (25) /* Cortex-A55 Virtual Maintenance Interrupt */ +#define IMX9_IRQ_HYPERVISORTIMER (26) /* Cortex-A55 Hypervisor Timer Interrupt */ +#define IMX9_IRQ_VIRTUALTIMER (27) /* Cortex-A55 Virtual Timer Interrupt */ +#define IMX9_IRQ_LEGACYFASTINT (28) /* Cortex-A55 Legacy nFIQ signal Interrupt */ +#define IMX9_IRQ_SECUREPHYTIMER (29) /* Cortex-A55 Secure Physical Timer Interrupt */ +#define IMX9_IRQ_NONSECUREPHYTIMER (30) /* Cortex-A55 Non-secure Physical Timer Interrupt */ +#define IMX9_IRQ_LEGACYIRQ (31) /* Cortex-A55 Legacy nIRQ Interrupt */ + +#define IMX9_IRQ_EXT (32) /* Vector number of the first ext int */ + +#endif /* __ARCH_ARM64_INCLUDE_IMX9_IRQ_H */ diff --git a/arch/arm64/src/Makefile b/arch/arm64/src/Makefile index fc1b4c9ffa053..efc08d9a76bd1 100644 --- a/arch/arm64/src/Makefile +++ b/arch/arm64/src/Makefile @@ -54,7 +54,7 @@ CSRCS = $(CHIP_CSRCS) $(CMN_CSRCS) COBJS = $(CSRCS:.c=$(OBJEXT)) SRCS = $(ASRCS) $(CSRCS) -OBJS = $(AOBJS) $(COBJS) +OBJS = $(AOBJS) $(COBJS) $(HEAD_OBJ) # User-mode objects diff --git a/arch/arm64/src/common/arm64_copystate.c b/arch/arm64/src/common/arm64_copystate.c index 47ddd39568aa7..8f3716f915e20 100644 --- a/arch/arm64/src/common/arm64_copystate.c +++ b/arch/arm64/src/common/arm64_copystate.c @@ -60,13 +60,13 @@ int arch_save_fpucontext(void *saveregs) { irqstate_t flags; - uint64_t *p_save; + uintptr_t p_save; /* Take a snapshot of the thread context right now */ flags = enter_critical_section(); - p_save = saveregs + XCPTCONTEXT_GP_SIZE; + p_save = (uintptr_t)saveregs + XCPTCONTEXT_GP_SIZE; arm64_fpu_save((struct fpu_reg *)p_save); ARM64_DSB(); diff --git a/arch/arm64/src/common/arm64_fpu.c b/arch/arm64/src/common/arm64_fpu.c index c8202b57a6243..69b458a9c524f 100644 --- a/arch/arm64/src/common/arm64_fpu.c +++ b/arch/arm64/src/common/arm64_fpu.c @@ -430,8 +430,10 @@ void arm64_fpu_disable(void) bool up_fpucmp(const void *saveregs1, const void *saveregs2) { - const uint64_t *regs1 = saveregs1 + XCPTCONTEXT_GP_SIZE; - const uint64_t *regs2 = saveregs2 + XCPTCONTEXT_GP_SIZE; + const uint64_t *regs1 = (uint64_t *)((uintptr_t)saveregs1 + + XCPTCONTEXT_GP_SIZE); + const uint64_t *regs2 = (uint64_t *)((uintptr_t)saveregs2 + + XCPTCONTEXT_GP_SIZE); /* Only compare callee-saved registers, caller-saved registers do not * need to be preserved. diff --git a/arch/arm64/src/common/arm64_head.S b/arch/arm64/src/common/arm64_head.S index 18ea5c97ea72f..f10dcd4005b68 100644 --- a/arch/arm64/src/common/arm64_head.S +++ b/arch/arm64/src/common/arm64_head.S @@ -89,6 +89,8 @@ label: .asciz msg; \ * This must be the very first address in the loaded image. * It should be loaded at any 4K-aligned address. */ + + .section .start, "ax" .globl __start; __start: diff --git a/arch/arm64/src/common/arm64_initialstate.c b/arch/arm64/src/common/arm64_initialstate.c index 0dc836e7a4725..b54532ba71cbb 100644 --- a/arch/arm64/src/common/arm64_initialstate.c +++ b/arch/arm64/src/common/arm64_initialstate.c @@ -56,7 +56,7 @@ void arm64_new_task(struct tcb_s * tcb) { - char *stack_ptr = tcb->stack_base_ptr + tcb->adj_stack_size; + uint64_t stack_ptr = (uintptr_t)tcb->stack_base_ptr + tcb->adj_stack_size; struct regs_context *pinitctx; #ifdef CONFIG_ARCH_FPU @@ -67,7 +67,7 @@ void arm64_new_task(struct tcb_s * tcb) /* set fpu context */ arm64_init_fpu(tcb); - stack_ptr = (char *)pfpuctx; + stack_ptr = (uintptr_t)pfpuctx; #endif pinitctx = STACK_PTR_TO_FRAME(struct regs_context, stack_ptr); diff --git a/arch/arm64/src/common/arm64_internal.h b/arch/arm64/src/common/arm64_internal.h index a1a98d456fab3..a68b356e53708 100644 --- a/arch/arm64/src/common/arm64_internal.h +++ b/arch/arm64/src/common/arm64_internal.h @@ -308,6 +308,10 @@ void arm64_pginitialize(void); uint64_t * arm64_syscall_switch(uint64_t *regs); int arm64_syscall(uint64_t *regs); +/* Low level serial output **************************************************/ + +void arm64_lowputc(char ch); + #ifdef USE_SERIALDRIVER /**************************************************************************** * Name: arm64_serialinit diff --git a/arch/arm64/src/imx9/Kconfig b/arch/arm64/src/imx9/Kconfig new file mode 100644 index 0000000000000..9ab957be0133a --- /dev/null +++ b/arch/arm64/src/imx9/Kconfig @@ -0,0 +1,225 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_IMX9 + +menu "i.MX9 Chip Selection" + +choice + prompt "i.MX9 Core Configuration" + default ARCH_CHIP_IMX93 + +config ARCH_CHIP_IMX93 + bool "i.MX9 Application Processor" + select ARCH_HAVE_MULTICPU + select ARMV8A_HAVE_GICv3 + select ARCH_CORTEX_A55 + select ARCH_HAVE_PWM_MULTICHAN + +endchoice # i.MX9 Chip Selection + +endmenu # "i.MX9 Chip Selection" + +config IMX9_FLEXIO_PWM + bool + select PWM_MULTICHAN + default n + +menu "i.MX9 Peripheral Selection" +config IMX9_UART1 + bool "UART1" + default n + select UART1_SERIALDRIVER + +config IMX9_FLEXIO1_PWM + depends on PWM + bool "Enable FLEXIO1 based PWM generation" + select IMX9_FLEXIO_PWM + default n + +config IMX9_FLEXIO2_PWM + depends on PWM + bool "Enable FLEXIO2 based PWM generation" + select IMX9_FLEXIO_PWM + default n + +config IMX9_FLEXIO1_PWM_NCHANNELS + depends on IMX9_FLEXIO1_PWM + int "Number of channels for FLEXIO1" + default 4 + range 1 7 + +config IMX9_FLEXIO1_PWM_CHANNEL_PINS + depends on IMX9_FLEXIO1_PWM + hex "FlexIO outputs used for FLEXIO1 timers" + default 0x0000000007060504 + +config IMX9_FLEXIO2_PWM_NCHANNELS + depends on IMX9_FLEXIO2_PWM + int "Number of channels for FLEXIO2" + default 1 + range 1 7 + +config IMX9_FLEXIO2_PWM_CHANNEL_PINS + depends on IMX9_FLEXIO2_PWM + hex "FlexIO outputs used for FLEXIO2 timers" + default 0x0000000000000000 + +config IMX9_TPM_PWM + bool + select PWM_MULTICHAN + default n + +config IMX9_TPM1_PWM + depends on PWM + bool "Enable TPM1 based PWM generation" + select IMX9_TPM_PWM + default n + +config IMX9_TPM1_PWM_NCHANNELS + depends on IMX9_TPM1_PWM + int "Number of channels for TPM1" + default 1 + +config IMX9_TPM1_PWM_CHMUX + depends on IMX9_TPM1_PWM + hex "Channel mux for TPM1" + default 0x03020100 + +config IMX9_TPM2_PWM + depends on PWM + bool "Enable TPM2 based PWM generation" + select IMX9_TPM_PWM + default n + +config IMX9_TPM2_PWM_NCHANNELS + depends on IMX9_TPM2_PWM + int "Number of channels for TPM2" + default 1 + +config IMX9_TPM2_PWM_CHMUX + depends on IMX9_TPM2_PWM + hex "Channel mux for TPM2" + default 0x03020100 + +config IMX9_TPM3_PWM + depends on PWM + bool "Enable TPM3 based PWM generation" + select IMX9_TPM_PWM + default n + +config IMX9_TPM3_PWM_NCHANNELS + depends on IMX9_TPM3_PWM + int "Number of channels for TPM3" + default 1 + +config IMX9_TPM3_PWM_CHMUX + depends on IMX9_TPM3_PWM + hex "Channel mux for TPM3" + default 0x03020100 + +config IMX9_TPM4_PWM + depends on PWM + bool "Enable TPM4 based PWM generation" + select IMX9_TPM_PWM + default n + +config IMX9_TPM4_PWM_NCHANNELS + depends on IMX9_TPM4_PWM + int "Number of channels for TPM4" + default 1 + +config IMX9_TPM4_PWM_CHMUX + depends on IMX9_TPM4_PWM + hex "Channel mux for TPM4" + default 0x03020100 + +config IMX9_TPM5_PWM + depends on PWM + bool "Enable TPM5 based PWM generation" + select IMX9_TPM_PWM + default n + +config IMX9_TPM5_PWM_NCHANNELS + depends on IMX9_TPM5_PWM + int "Number of channels for TPM5" + default 1 + +config IMX9_TPM5_PWM_CHMUX + depends on IMX9_TPM5_PWM + hex "Channel mux for TPM5" + default 0x03020100 + +config IMX9_TPM6_PWM + depends on PWM + bool "Enable TPM6 based PWM generation" + select IMX9_TPM_PWM + default n + +config IMX9_TPM6_PWM_NCHANNELS + depends on IMX9_TPM6_PWM + int "Number of channels for TPM6" + default 1 + +config IMX9_TPM6_PWM_CHMUX + depends on IMX9_TPM6_PWM + hex "Channel mux for TPM6" + default 0x03020100 + +config IMX9_USBDEV + bool + default n + select USBDEV + +config IMX9_USBDEV_USBC1 + bool "USB Device using controller 1" + default n + select IMX9_USBDEV + +config IMX9_USBDEV_USBC2 + depends on !IMX9_USBDEV_USBC1 + bool "USB Device using controller 2" + default n + select IMX9_USBDEV + +if IMX9_USBDEV + +menu "USB device controller driver (DCD) options" + +config IMX9_USBDEV_NOVBUS + bool "No USB VBUS sensing" + default n + +config IMX9_USBDEV_FRAME_INTERRUPT + bool "USB frame interrupt" + default n + ---help--- + Handle USB Start-Of-Frame events. Enable reading SOF from interrupt + handler vs. simply reading on demand. Probably a bad idea... Unless + there is some issue with sampling the SOF from hardware asynchronously. + +config IMX9_USBDEV_REGDEBUG + bool "Register level debug" + depends on DEBUG_USB_INFO + default n + ---help--- + Output detailed register-level USB device debug information. Requires + also CONFIG_DEBUG_USB_INFO. + +endmenu # USB device controller driver (DCD) options + +endif # IMX9_USBDEV + +endmenu # iMX Peripheral Selection + +config IMX9_GPIO_IRQ + bool "GPIO Interrupt Support" + default n + +config IMX9_PLL + bool "PLL setup support (WIP)" + default n + +endif # ARCH_CHIP_IMX9 diff --git a/arch/arm64/src/imx9/Make.defs b/arch/arm64/src/imx9/Make.defs new file mode 100644 index 0000000000000..0d7427aec3eb0 --- /dev/null +++ b/arch/arm64/src/imx9/Make.defs @@ -0,0 +1,48 @@ +############################################################################ +# arch/arm64/src/imx9/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include common/Make.defs + +# i.MX9-specific C source files + +CHIP_CSRCS = imx9_boot.c imx9_ccm.c imx9_clockconfig.c imx9_gpio.c imx9_iomuxc.c + +ifeq ($(CONFIG_ARCH_CHIP_IMX93),y) + CHIP_CSRCS += imx9_lpuart.c + ifeq ($(CONFIG_ARCH_EARLY_PRINT),y) + CHIP_ASRCS = imx93_lowputc.S + endif +endif + +ifeq ($(CONFIG_IMX9_GPIO_IRQ),y) + CHIP_CSRCS += imx9_gpioirq.c +endif + +ifeq ($(CONFIG_IMX9_FLEXIO_PWM),y) + CHIP_CSRCS += imx9_flexio_pwm.c +endif + +ifeq ($(CONFIG_IMX9_TPM_PWM),y) + CHIP_CSRCS += imx9_tpm_pwm.c +endif + +ifeq ($(CONFIG_IMX9_USBDEV),y) + CHIP_CSRCS += imx9_usbdev.c +endif diff --git a/arch/arm64/src/imx9/chip.h b/arch/arm64/src/imx9/chip.h new file mode 100644 index 0000000000000..f9792f5518e30 --- /dev/null +++ b/arch/arm64/src/imx9/chip.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * arch/arm64/src/imx9/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_CHIP_H +#define __ARCH_ARM64_SRC_IMX9_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Macro Definitions + ****************************************************************************/ + +#endif /* __ARCH_ARM64_SRC_IMX9_CHIP_H */ diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h b/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h new file mode 100644 index 0000000000000..ae46d228ff776 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h @@ -0,0 +1,701 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx93/imx93_ccm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_CCM_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_CCM_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets *********************************************************/ + +#define IMX9_CCM_CR_CTRL_OFFSET(n) (0x0000 + ((n) << 7)) /* Clock root control (CLOCK_ROOTn_CONTROL, n=0..94) */ +#define IMX9_CCM_CR_CTRL_SET_OFFSET(n) (0x0004 + ((n) << 7)) /* Clock root control (CLOCK_ROOTn_CONTROL_SET, n=0..94) */ +#define IMX9_CCM_CR_CTRL_CLR_OFFSET(n) (0x0008 + ((n) << 7)) /* Clock root control (CLOCK_ROOTn_CONTROL_CLR, n=0..94) */ +#define IMX9_CCM_CR_CTRL_TOG_OFFSET(n) (0x000c + ((n) << 7)) /* Clock root control (CLOCK_ROOTn_CONTROL_TOG, n=0..94) */ +#define IMX9_CCM_CR_STAT0_OFFSET(n) (0x0020 + ((n) << 7)) /* Clock root working status (CLOCK_ROOTn_STATUS0, n=0..94) */ +#define IMX9_CCM_CR_AUTH_OFFSET(n) (0x0030 + ((n) << 7)) /* Clock root access control (CLOCK_ROOTn_AUTHEN, n=0..94) */ +#define IMX9_CCM_CR_AUTH_SET_OFFSET(n) (0x0034 + ((n) << 7)) /* Clock root access control (CLOCK_ROOTn_AUTHEN_SET, n=0..94) */ +#define IMX9_CCM_CR_AUTH_CLR_OFFSET(n) (0x0038 + ((n) << 7)) /* Clock root access control (CLOCK_ROOTn_AUTHEN_CLR, n=0..94) */ +#define IMX9_CCM_CR_AUTH_TOG_OFFSET(n) (0x003c + ((n) << 7)) /* Clock root access control (CLOCK_ROOTn_AUTHEN_TOG, n=0..94) */ + +#define IMX9_CCM_GPR_SH_OFFSET(n) (0x4800 + ((n) << 5)) /* General Purpose Register (GPR_SHAREDn, n=0..7) */ +#define IMX9_CCM_GPR_SH_SET_OFFSET(n) (0x4804 + ((n) << 5)) /* General Purpose Register (GPR_SHAREDn_SET, n=0..7) */ +#define IMX9_CCM_GPR_SH_CLR_OFFSET(n) (0x4808 + ((n) << 5)) /* General Purpose Register (GPR_SHAREDn_CLR, n=0..7) */ +#define IMX9_CCM_GPR_SH_TOG_OFFSET(n) (0x480c + ((n) << 5)) /* General Purpose Register (GPR_SHAREDn_TOG, n=0..7) */ +#define IMX9_CCM_GPR_SH_AUTH_OFFSET(n) (0x4810 + ((n) << 5)) /* General Purpose Register (GPR_SHAREDn_AUTHEN, n=0..7) */ +#define IMX9_CCM_GPR_SH_AUTH_SET_OFFSET(n) (0x4814 + ((n) << 5)) /* General Purpose Register (GPR_SHAREDn_AUTHEN_SET, n=0..7) */ +#define IMX9_CCM_GPR_SH_AUTH_CLR_OFFSET(n) (0x4818 + ((n) << 5)) /* General Purpose Register (GPR_SHAREDn_AUTHEN_CLR, n=0..7) */ +#define IMX9_CCM_GPR_SH_AUTH_TOG_OFFSET(n) (0x481c + ((n) << 5)) /* General Purpose Register (GPR_SHAREDn_AUTHEN_TOG, n=0..7) */ + +#define IMX9_CCM_GPR_PR_OFFSET(n) (0x4c00 + (((n)-1) << 5)) /* General Purpose Register (GPR_PRIVATEn, n=1..7) */ +#define IMX9_CCM_GPR_PR_SET_OFFSET(n) (0x4c04 + (((n)-1) << 5)) /* General Purpose Register (GPR_PRIVATEn_SET, n=1..7) */ +#define IMX9_CCM_GPR_PR_CLR_OFFSET(n) (0x4c08 + (((n)-1) << 5)) /* General Purpose Register (GPR_PRIVATEn_CLR, n=1..7) */ +#define IMX9_CCM_GPR_PR_TOG_OFFSET(n) (0x4c0c + (((n)-1) << 5)) /* General Purpose Register (GPR_PRIVATEn_TOG, n=1..7) */ +#define IMX9_CCM_GPR_PR_AUTH_OFFSET(n) (0x4c10 + (((n)-1) << 5)) /* General Purpose Register (GPR_PRIVATEn_AUTHEN, n=1..7) */ +#define IMX9_CCM_GPR_PR_AUTH_SET_OFFSET(n) (0x4c14 + (((n)-1) << 5)) /* General Purpose Register (GPR_PRIVATEn_AUTHEN_SET, n=1..7) */ +#define IMX9_CCM_GPR_PR_AUTH_CLR_OFFSET(n) (0x4c18 + (((n)-1) << 5)) /* General Purpose Register (GPR_PRIVATEn_AUTHEN_CLR, n=1..7) */ +#define IMX9_CCM_GPR_PR_AUTH_TOG_OFFSET(n) (0x4c1c + (((n)-1) << 5)) /* General Purpose Register (GPR_PRIVATEn_AUTHEN_TOG, n=1..7) */ + +#define IMX9_CCM_OSCPLL_DIR_OFFSET(n) (0x5000 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..18) */ +#define IMX9_CCM_OSCPLL_LPM_STAT0_OFFSET(n) (0x5004 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..18) */ +#define IMX9_CCM_OSCPLL_LPM_STAT1_OFFSET(n) (0x5008 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..18) */ +#define IMX9_CCM_OSCPLL_LPM0_OFFSET(n) (0x5010 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..18) */ +#define IMX9_CCM_OSCPLL_LPM1_OFFSET(n) (0x5014 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..18) */ +#define IMX9_CCM_OSCPLL_LPM_CUR_OFFSET(n) (0x501C + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..18) */ +#define IMX9_CCM_OSCPLL_STAT0_OFFSET(n) (0x5020 + ((n) << 6)) /* Clock source working status (OSCPLLn_STATUS0, n=0..18) */ +#define IMX9_CCM_OSCPLL_STAT1_OFFSET(n) (0x5024 + ((n) << 6)) /* Clock source low power status (OSCPLLn_STATUS1, n=0..18) */ +#define IMX9_CCM_OSCPLL_AUTH_OFFSET(n) (0x5030 + ((n) << 6)) /* Clock source access control (OSCPLLn_AUTHEN, n=0..18) */ + +#define IMX9_CCM_LPCG_DIR_OFFSET(n) (0x8000 + ((n) << 6)) /* LPCG direct control (LPCGn_DIRECT, n=0..126) */ +#define IMX9_CCM_LPCG_LPM_STAT0_OFFSET(n) (0x8004 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..126) */ +#define IMX9_CCM_LPCG_LPM_STAT1_OFFSET(n) (0x8008 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..126) */ +#define IMX9_CCM_LPCG_LPM0_OFFSET(n) (0x8010 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..126) */ +#define IMX9_CCM_LPCG_LPM1_OFFSET(n) (0x8014 + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..126) */ +#define IMX9_CCM_LPCG_LPM_CUR_OFFSET(n) (0x801C + ((n) << 6)) /* Clock source direct control (OSCPLLn_DIRECT, n=0..126) */ +#define IMX9_CCM_LPCG_STAT0_OFFSET(n) (0x8020 + ((n) << 6)) /* LPCG working status (LPCGn_STATUS0, n=0..126) */ +#define IMX9_CCM_LPCG_STAT1_OFFSET(n) (0x8024 + ((n) << 6)) /* LPCG low power status (LPCGn_STATUS1, n=0..126) */ +#define IMX9_CCM_LPCG_AUTH_OFFSET(n) (0x8030 + ((n) << 6)) /* LPCG access control (LPCGn_AUTHEN, n=0..126) */ + +/* Register addresses *******************************************************/ + +#define IMX9_CCM_CR_CTRL(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_CTRL_OFFSET(n)) +#define IMX9_CCM_CR_CTRL_SET(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_CTRL_SET_OFFSET(n)) +#define IMX9_CCM_CR_CTRL_CLR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_CTRL_CLR_OFFSET(n)) +#define IMX9_CCM_CR_CTRL_TOG(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_CTRL_TOG_OFFSET(n)) +#define IMX9_CCM_CR_STAT0(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_STAT0_OFFSET(n)) +#define IMX9_CCM_CR_AUTH(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_AUTH_OFFSET(n)) +#define IMX9_CCM_CR_AUTH_SET(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_AUTH_SET_OFFSET(n)) +#define IMX9_CCM_CR_AUTH_CLR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_AUTH_CLR_OFFSET(n)) +#define IMX9_CCM_CR_AUTH_TOG(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_CR_AUTH_TOG_OFFSET(n)) + +#define IMX9_CCM_GPR_SH(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_SH_OFFSET(n)) +#define IMX9_CCM_GPR_SH_SET(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_SH_SET_OFFSET(n)) +#define IMX9_CCM_GPR_SH_CLR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_SH_CLR_OFFSET(n)) +#define IMX9_CCM_GPR_SH_TOG(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_SH_TOG_OFFSET(n)) +#define IMX9_CCM_GPR_SH_AUTH(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_SH_AUTH_OFFSET(n)) +#define IMX9_CCM_GPR_SH_AUTH_SET(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_SH_AUTH_SET_OFFSET(n)) +#define IMX9_CCM_GPR_SH_AUTH_CLR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_SH_AUTH_CLR_OFFSET(n)) +#define IMX9_CCM_GPR_SH_AUTH_TOG(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_SH_AUTH_TOG_OFFSET(n)) + +#define IMX9_CCM_GPR_PR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_PR_OFFSET(n)) +#define IMX9_CCM_GPR_PR_SET(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_PR_SET_OFFSET(n)) +#define IMX9_CCM_GPR_PR_CLR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_PR_CLR_OFFSET(n)) +#define IMX9_CCM_GPR_PR_TOG(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_PR_TOG_OFFSET(n)) +#define IMX9_CCM_GPR_PR_AUTH(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_PR_AUTH_OFFSET(n)) +#define IMX9_CCM_GPR_PR_AUTH_SET(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_PR_AUTH_SET_OFFSET(n)) +#define IMX9_CCM_GPR_PR_AUTH_CLR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_PR_AUTH_CLR_OFFSET(n)) +#define IMX9_CCM_GPR_PR_AUTH_TOG(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_GPR_PR_AUTH_TOG_OFFSET(n)) + +#define IMX9_CCM_OSCPLL_DIR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_DIR_OFFSET(n)) +#define IMX9_CCM_OSCPLL_LPM_STAT0(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_LPM_STAT0_OFFSET(n)) +#define IMX9_CCM_OSCPLL_LPM_STAT1(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_LPM_STAT1_OFFSET(n)) +#define IMX9_CCM_OSCPLL_LPM0(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_LPM0_OFFSET(n)) +#define IMX9_CCM_OSCPLL_LPM1(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_LPM1_OFFSET(n)) +#define IMX9_CCM_OSCPLL_LPM_CUR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_LPM1_OFFSET(n)) +#define IMX9_CCM_OSCPLL_STAT0(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_STAT0_OFFSET(n)) +#define IMX9_CCM_OSCPLL_STAT1(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_STAT1_OFFSET(n)) +#define IMX9_CCM_OSCPLL_AUTH(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_OSCPLL_AUTH_OFFSET(n)) + +#define IMX9_CCM_LPCG_DIR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_DIR_OFFSET(n)) +#define IMX9_CCM_LPCG_LPM_STAT0(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_LPM_STAT0_OFFSET(n)) +#define IMX9_CCM_LPCG_LPM_STAT1(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_LPM_STAT1_OFFSET(n)) +#define IMX9_CCM_LPCG_LPM0(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_LPM0_OFFSET(n)) +#define IMX9_CCM_LPCG_LPM1(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_LPM1_OFFSET(n)) +#define IMX9_CCM_LPCG_LPM_CUR(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_LPM1_OFFSET(n)) +#define IMX9_CCM_LPCG_STAT0(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_STAT0_OFFSET(n)) +#define IMX9_CCM_LPCG_STAT1(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_STAT1_OFFSET(n)) +#define IMX9_CCM_LPCG_AUTH(n) (IMX9_CCM_CTRL_BASE + IMX9_CCM_LPCG_AUTH_OFFSET(n)) + +/* Register bit definitions *************************************************/ + +/* Clock root control (CLOCK_ROOTn_CONTROL, n=0..94) */ + +#define CCM_CR_CTRL_DIV_SHIFT (0) /* Bits 0-7: Divide selected clock by DIV+1 (DIV) */ +#define CCM_CR_CTRL_DIV_MASK (0xff << CCM_CR_CTRL_DIV_SHIFT) +# define CCM_CR_CTRL_DIV(n) (((n)-1) << CCM_CR_CTRL_DIV_SHIFT) /* Divide selected clock by n */ + +#define CCM_CR_CTRL_MUX_SHIFT (8) /* Bits 8-9: Select clock from 8 clock sources (MUX) */ +#define CCM_CR_CTRL_MUX_MASK (0x03 << CCM_CR_CTRL_MUX_SHIFT) +# define CCM_CR_CTRL_MUX_SRCSEL(n) ((n) << CCM_CR_CTRL_MUX_SHIFT) /* Select clock source n */ + + /* Bits 11-23: Reserved */ +#define CCM_CR_CTRL_OFF (1 << 24) /* Bit 24: Shutdown clock root (OFF) */ + /* Bits 25-31: Reserved */ + +/* Clock root working status (CLOCK_ROOTn_STATUS0, n=0..94) */ + +#define CCM_CR_STAT0_DIV_SHIFT (0) /* Bits 0-7: Current clock root DIV setting (DIV) */ +#define CCM_CR_STAT0_DIV_MASK (0xff << CCM_CR_STAT0_DIV_SHIFT) +#define CCM_CR_STAT0_MUX_SHIFT (8) /* Bits 8-9: Current clock root MUX setting (MUX) */ +#define CCM_CR_STAT0_MUX_MASK (0x03 << CCM_CR_STAT0_MUX_SHIFT) + /* Bits 11-23: Reserved */ +#define CCM_CR_STAT0_OFF (1 << 24) /* Bit 24: Current clock root OFF setting (OFF) */ + /* Bits 25-27: Reserved */ +#define CCM_CR_STAT0_SLICE_BUSY (1 << 28) /* Bit 28: Clock generation logic is applying the new setting (SLICE_BUSY) */ +#define CCM_CR_STAT0_CHANGING (1 << 31) /* Bit 31: Clock generation logic is updating currently (CHANGING) */ + +/* Clock root access control (CLOCK_ROOTn_AUTHEN, n=0..94) */ + +#define CCM_CR_AUTH_TZ_USER (1 << 8) /* Bit 8: Clock root can be changed in user mode (TZ_USER) */ +#define CCM_CR_AUTH_TZ_NS (1 << 9) /* Bit 9: Clock root can be changed in non-secure mode (TZ_NS) */ + /* Bit 10: Reserved */ +#define CCM_CR_AUTH_LOCK_TZ (1 << 11) /* Bit 1: Lock TrustZone settings (LOCK_TZ) */ + /* Bits 12-14: Reserved */ +#define CCM_CR_AUTH_LOCK_LIST (1 << 12) /* Bit 15: Lock whitelist settings (LOCK_LIST) */ +#define CCM_CR_AUTH_WHITE_LIST_SHIFT (16) /* Bits 16-31: Allow domains to change clock (WHITE_LIST) */ +#define CCM_CR_AUTH_WHITE_LIST_MASK (0xffff << CCM_CR_AUTH_WHITE_LIST_SHIFT) + +/* General Purpose Register (GPR_SHAREDn, n=0..7) */ + +#define CCM_GPR_SH_GPR_SHIFT (0) /* Bits 0-31: General purpose register, shared for all CPU domains (GPR) */ +#define CCM_GPR_SH_GPR_MASK (0xffffffff << CCM_GPR_SH_GPR_SHIFT) + +/* General Purpose Register (GPR_SHAREDn_AUTHEN, n=0..7) */ + +#define CCM_GPR_SH_AUTH_TZ_USER (1 << 8) /* Bit 8: Clock root can be changed in user mode (TZ_USER) */ +#define CCM_GPR_SH_AUTH_TZ_NS (1 << 9) /* Bit 9: Clock root can be changed in non-secure mode (TZ_NS) */ + /* Bit 10: Reserved */ +#define CCM_GPR_SH_AUTH_LOCK_TZ (1 << 11) /* Bit 1: Lock TrustZone settings (LOCK_TZ) */ + /* Bits 12-14: Reserved */ +#define CCM_GPR_SH_AUTH_LOCK_LIST (1 << 12) /* Bit 15: Lock whitelist settings (LOCK_LIST) */ +#define CCM_GPR_SH_AUTH_WHITE_LIST_SHIFT (16) /* Bits 16-31: Allow domains to change clock (WHITE_LIST) */ +#define CCM_GPR_SH_AUTH_WHITE_LIST_MASK (0xffff << CCM_GPR_SH_AUTH_WHITE_LIST_SHIFT) + +/* General Purpose Register (GPR_PRIVATEn, n=1..7) */ + +#define CCM_GPR_PR_GPR_SHIFT (0) /* Bits 0-31: General purpose register, with dedicated bits for each domain (GPR) */ +#define CCM_GPR_PR_GPR_MASK (0xffffffff << CCM_GPR_PR_GPR_SHIFT) + +/* General Purpose Register (GPR_PRIVATEn_AUTHEN, n=1..7) */ + +#define CCM_GPR_PR_AUTH_TZ_USER (1 << 8) /* Bit 8: Clock root can be changed in user mode (TZ_USER) */ +#define CCM_GPR_PR_AUTH_TZ_NS (1 << 9) /* Bit 9: Clock root can be changed in non-secure mode (TZ_NS) */ + /* Bit 10: Reserved */ +#define CCM_GPR_PR_AUTH_LOCK_TZ (1 << 11) /* Bit 1: Lock TrustZone settings (LOCK_TZ) */ + /* Bits 12-14: Reserved */ +#define CCM_GPR_PR_AUTH_LOCK_LIST (1 << 12) /* Bit 15: Lock whitelist settings (LOCK_LIST) */ +#define CCM_GPR_PR_AUTH_WHITE_LIST_SHIFT (16) /* Bits 16-31: Allow domains to change clock (WHITE_LIST) */ +#define CCM_GPR_PR_AUTH_WHITE_LIST_MASK (0xffff << CCM_CR_AUTH_WHITE_LIST_SHIFT) + +/* Clock source direct control (OSCPLLn_DIRECT, n=0..18) */ + +#define CCM_OSCPLL_DIR_ON (1 << 0) /* Bit 0: Turn on clock source (ON) */ + /* Bits 1-31: Reserved */ + +/* Clock source LPM status (OSCPLLn_LPM_STATUS0/1, n=0..18) */ + +#define CCM_OSCPLL_LPM_STAT_CPU_MODE_SHIFT (0) /* Bits 0-1: Current mode of CPU */ +#define CCM_OSCPLL_LPM_STAT_CPU_MODE_MASK (0x03 << CCM_OSCPLL_LPM_STAT_CPU_MODE_SHIFT) +#define CCM_OSCPLL_LPM_STAT_CPU_TRANS_REQ_SHIFT (2) /* Bit 2: Domain request pending */ +#define CCM_OSCPLL_LPM_STAT_CPU_TRANS_REQ_MASK (0x01 << CCM_OSCPLL_LPM_STAT_CPU_TRANS_REQ_SHIFT) +# define CCM_OSCPLL_LPM_STAT_ON (0) /* CPU is in RUN mode */ +# define CCM_OSCPLL_LPM_STAT_WAIT (1) /* CPU is in WAIT mode */ +# define CCM_OSCPLL_LPM_STAT_STOP (2) /* CPU is in STOP mode */ +# define CCM_OSCPLL_LPM_STAT_SUSPED (3) /* CPU is in SUSPEND mode */ + +/* CPU domain[n] from OSCPLLn_LPM_STATUS0/1 */ + +#define CCM_OSCPLL_LPM_STAT_CPU_DOMAIN_SHIFT (4) +#define CCM_OSCPLL_LPM_STAT_CPU_DOMAIN(n) ((n) * CCM_OSCPLL_LPM_STAT_CPU_DOMAIN_SHIFT) +#define CCM_OSCPLL_LPM_STAT_CPU_MODE_GET(n, v) (((v) >> CCM_OSCPLL_LPM_STAT_CPU_DOMAIN(n)) & CCM_OSCPLL_LPM_STAT_CPU_MODE_MASK) + +/* Clock source LPM mode (OSCPLLn_LPM_0/1 and _CUR, n=0..18) */ + +#define CCM_OSCPLL_LPM_MODE_SHIFT (0) /* Bits 0-2: Current mode of CPU */ +#define CCM_OSCPLL_LPM_MODE_MASK (0x07 << CCM_OSCPLL_LPM_MODE_SHIFT) +# define CCM_OSCPLL_LPM_MODE_OFF (0) /* Clock is off during all modes */ +# define CCM_OSCPLL_LPM_MODE_RUN (1) /* Clock is on in run mode, but off in WAIT and STOP modes */ +# define CCM_OSCPLL_LPM_MODE_RUNWAIT (2) /* Clock is on in run and wait modes, but off in STOP modes */ +# define CCM_OSCPLL_LPM_MODE_RUNWAITSTOP (3) /* Clock is on during all modes, except SUSPEND mode */ +# define CCM_OSCPLL_LPM_MODE_ALL (4) /* Clock is on during all modes */ + +/* CPU domain[n] from OSCPLLn_LPM_0/1 */ + +#define CCM_OSCPLL_LPM_MODE_CPU_DOMAIN_SHIFT (4) +#define CCM_OSCPLL_LPM_MODE_CPU_DOMAIN(n) ((n) * CCM_OSCPLL_LPM_MODE_CPU_DOMAIN_SHIFT) +#define CCM_OSCPLL_LPM_MODE_CPU_MODE_SET(n, v) ((v) & CCM_OSCPLL_LPM_MODE_MASK << CCM_LPCG_LPM_MODE_CPU_DOMAIN(n)) +#define CCM_OSCPLL_LPM_MODE_CPU_MODE_GET(n, v) (((v) >> CCM_LPCG_LPM_STAT_CPU_DOMAIN(n)) & CCM_OSCPLL_LPM_MODE_MASK) + +/* Clock source working status (OSCPLLn_STATUS0, n=0..18) */ + +#define CCM_OSCPLL_STAT0_ON (1 << 0) /* Bit 0: Clock source is turned on (ON) */ + /* Bits 1-3: Reserved */ +#define CCM_OSCPLL_STAT0_STATUS_EARLY (1 << 4) /* Bit 4: Clock source is active (STATUS_EARLY) */ +#define CCM_OSCPLL_STAT0_STATUS_LATE (1 << 5) /* Bit 5: Clock source is ready to use (STATUS_LATE) */ + /* Bits 6-11: Reserved */ +#define CCM_OSCPLL_STAT0_IN_USE (1 << 12) /* Bit 28: Indicates whether the clock source is being used by active clock roots (IN_USE) */ + /* Bits 16-31: Reserved */ + +/* Clock source low power status (OSCPLLn_STATUS1, n=0..18) */ + +#define CCM_OSCPLL_STAT1_DOM_ACTIVE_SHIFT (0) /* Bits 0-15: Domain active */ +#define CCM_OSCPLL_STAT1_DOM_ACTIVE_MASK (0xffff << CCM_OSCPLL_STAT1_DOM_ACTIVE_SHIFT) +#define CCM_OSCPLL_STAT1_DOM_ENABLE_SHIFT (16) /* Bits 16-32: Domain enabled */ +#define CCM_OSCPLL_STAT1_DOM_ENABLE_MASK (0xffff << CCM_OSCPLL_STAT1_DOM_ENABLE_SHIFT) + +/* Clock source access control (OSCPLLn_AUTHEN, n=0..18) */ + +#define CCM_OSCPLL_AUTH_CPULPM (1 << 2) /* Bit 2: CPU Low Power Mode (CPULPM) */ +#define CCM_OSCPLL_AUTH_AUTO_CTRL (1 << 3) /* Bit 2: Auto mode (AUTO_CTRL) */ +#define CCM_OSCPLL_AUTH_LOCK_MODE (1 << 7) /* Bit 7: Lock low power and access mode (LOCK_MODE) */ +#define CCM_OSCPLL_AUTH_TZ_USER (1 << 8) /* Bit 8: Clock source can be changed in user mode (TZ_USER) */ +#define CCM_OSCPLL_AUTH_TZ_NS (1 << 9) /* Bit 9: Clock source can be changed in non-secure mode (TZ_NS) */ + /* Bit 10: Reserved */ +#define CCM_OSCPLL_AUTH_LOCK_TZ (1 << 11) /* Bit 11: Lock TrustZone settings (LOCK_TZ) */ + /* Bits 12-14: Reserved */ +#define CCM_OSCPLL_AUTH_LOCK_LIST (1 << 15) /* Bit 15: Lock whitelist settings (LOCK_LIST) */ +#define CCM_OSCPLL_AUTH_WHITE_LIST_SHIFT (16) /* Bits 16-31: Allow domains to change clock (WHITE_LIST) */ +#define CCM_OSCPLL_AUTH_WHITE_LIST_MASK (0xffff << CCM_OSCPLL_AUTH_WHITE_LIST_SHIFT) + +/* LPCG direct control (LPCGn_DIRECT, n=0..126) */ + +#define CCM_LPCG_DIR_ON (1 << 0) /* Bit 0: LPCG on (ON) */ + /* Bit 1: Reserved */ +#define CCM_LPCG_ACK_TIMEOUT_EN (1 << 2) /* Bit 2: Ack timeout enable */ + /* Bits 3-31: Reserved */ + +/* Clock source LPM status (LPCGn_LPM_STATUS0/1, n=0..18) */ + +#define CCM_LPCG_LPM_STAT_CPU_MODE_SHIFT (0) /* Bits 0-1: Current mode of CPU */ +#define CCM_LPCG_LPM_STAT_CPU_MODE_MASK (0x03 << CCM_LPCG_LPM_STAT_CPU_MODE_SHIFT) +#define CCM_LPCG_LPM_STAT_CPU_TRANS_REQ_SHIFT (2) /* Bit 2: Domain request pending */ +#define CCM_LPCG_LPM_STAT_CPU_TRANS_REQ_MASK (0x01 << CCM_LPCG_LPM_STAT_CPU_TRANS_REQ_SHIFT) +# define CCM_LPCG_LPM_STAT_ON (0) /* CPU is in RUN mode */ +# define CCM_LPCG_LPM_STAT_WAIT (1) /* CPU is in WAIT mode */ +# define CCM_LPCG_LPM_STAT_STOP (2) /* CPU is in STOP mode */ +# define CCM_LPCG_LPM_STAT_SUSPED (3) /* CPU is in SUSPEND mode */ + +/* CPU domain[n] from OSCPLLn_LPM_STATUS0/1 */ + +#define CCM_LPCG_LPM_STAT_CPU_DOMAIN_SHIFT (4) +#define CCM_LPCG_LPM_STAT_CPU_DOMAIN(n) ((n) * CCM_LPCG_LPM_STAT_CPU_DOMAIN_SHIFT) +#define CCM_LPCG_LPM_STAT_CPU_MODE_GET(n, v) (((v) >> CCM_LPCG_LPM_STAT_CPU_DOMAIN(n)) & CCM_LPCG_LPM_STAT_CPU_MODE_MASK) + +/* Clock source LPM mode (LPCGn_LPM_0/1 and _CUR, n=0..18) */ + +#define CCM_LPCG_LPM_MODE_SHIFT (0) /* Bits 0-2: Current mode of CPU */ +#define CCM_LPCG_LPM_MODE_MASK (0x07 << CCM_LPCG_LPM_MODE_SHIFT) +# define CCM_LPCG_LPM_MODE_OFF (0) /* Clock is off during all modes */ +# define CCM_LPCG_LPM_MODE_RUN (1) /* Clock is on in run mode, but off in WAIT and STOP modes */ +# define CCM_LPCG_LPM_MODE_RUNWAIT (2) /* Clock is on in run and wait modes, but off in STOP modes */ +# define CCM_LPCG_LPM_MODE_RUNWAITSTOP (3) /* Clock is on during all modes, except SUSPEND mode */ +# define CCM_LPCG_LPM_MODE_ALL (4) /* Clock is on during all modes */ + +/* CPU domain[n] from LPCGn_LPM_0/1 */ + +#define CCM_LPCG_LPM_MODE_CPU_DOMAIN_SHIFT (4) +#define CCM_LPCG_LPM_MODE_CPU_DOMAIN(n) ((n) * CCM_LPCG_LPM_MODE_CPU_DOMAIN_SHIFT) +#define CCM_LPCG_LPM_MODE_CPU_MODE_SET(n, v) ((v) & CCM_LPCG_LPM_MODE_MASK << CCM_LPCG_LPM_MODE_CPU_DOMAIN(n)) +#define CCM_LPCG_LPM_MODE_CPU_MODE_GET(n, v) (((v) >> CCM_LPCG_LPM_MODE_CPU_DOMAIN(n)) & CCM_LPCG_LPM_MODE_MASK) + +/* LPCG working status (LPCGn_STATUS0, n=0..126) */ + +#define CCM_LPCG_STAT0_ON (1 << 0) /* Bit 0: Clock source is turned on (ON) */ + /* Bits 1-31 Reserved */ + +/* LPCG low power status (LPCGn_STATUS1, n=0..126) */ + +#define CCM_LPCG_STAT0_ACTIVE_DOMAIN_SHIFT (8) /* Bits 8-11: Domains that own this clock source according to whitelist (ACTIVE_DOMAIN) */ +#define CCM_LPCG_STAT0_ACTIVE_DOMAIN_MASK (0x0f << CCM_LPCG_STAT0_ACTIVE_DOMAIN_SHIFT) +#define CCM_LPCG_STAT0_DOMAIN_ENABLE_SHIFT (8) /* Bits 12-15: Enable status from each domain (DOMAIN_ENABLE) */ +#define CCM_LPCG_STAT0_DOMAIN_ENABLE_MASK (0x0f << CCM_LPCG_STAT0_DOMAIN_ENABLE_SHIFT) + /* Bits 16-31: Reserved */ + +/* LPCG access control (LPCGn_AUTHEN, n=0..126) */ + +#define CCM_LPCG_AUTH_CPULPM (1 << 2) /* Bit 2: CPU Low Power Mode (CPULPM) */ +#define CCM_LPCG_AUTH_LOCK_MODE (1 << 7) /* Bit 7: Lock low power and access mode (LOCK_MODE) */ +#define CCM_LPCG_AUTH_TZ_USER (1 << 8) /* Bit 8: Clock source can be changed in user mode (TZ_USER) */ +#define CCM_LPCG_AUTH_TZ_NS (1 << 9) /* Bit 9: Clock source can be changed in non-secure mode (TZ_NS) */ + /* Bit 10: Reserved */ +#define CCM_LPCG_AUTH_LOCK_TZ (1 << 11) /* Bit 11: Lock TrustZone settings (LOCK_TZ) */ + /* Bits 12-14: Reserved */ +#define CCM_LPCG_AUTH_LOCK_LIST (1 << 15) /* Bit 15: Lock whitelist settings (LOCK_LIST) */ +#define CCM_LPCG_AUTH_WHITE_LIST_SHIFT (16) /* Bits 16-31: Allow domains to change clock (WHITE_LIST) */ +#define CCM_LPCG_AUTH_WHITE_LIST_MASK (0xffff << CCM_LPCG_AUTH_WHITE_LIST_SHIFT) + +/* Clock roots */ + +#define CCM_CR_A55PERIPH 0 /* CLOCK Root Arm A55 Periph. */ +#define CCM_CR_A55MTRBUS 1 /* CLOCK Root Arm A55 MTR BUS. */ +#define CCM_CR_A55 2 /* CLOCK Root Arm A55. */ +#define CCM_CR_M33 3 /* CLOCK Root M33. */ +#define CCM_CR_SENTINEL 4 /* CLOCK Root Sentinel. */ +#define CCM_CR_BUSWAKEUP 5 /* CLOCK Root Bus Wakeup. */ +#define CCM_CR_BUSAON 6 /* CLOCK Root Bus Aon. */ +#define CCM_CR_WAKEUPAXI 7 /* CLOCK Root Wakeup Axi. */ +#define CCM_CR_SWOTRACE 8 /* CLOCK Root Swo Trace. */ +#define CCM_CR_M33SYSTICK 9 /* CLOCK Root M33 Systick. */ +#define CCM_CR_FLEXIO1 10 /* CLOCK Root Flexio1. */ +#define CCM_CR_FLEXIO2 11 /* CLOCK Root Flexio2. */ +#define CCM_CR_LPIT1 12 /* CLOCK Root Lpit1. */ +#define CCM_CR_LPIT2 13 /* CLOCK Root Lpit2. */ +#define CCM_CR_LPTMR1 14 /* CLOCK Root Lptmr1. */ +#define CCM_CR_LPTMR2 15 /* CLOCK Root Lptmr2. */ +#define CCM_CR_TPM1 16 /* CLOCK Root Tpm1. */ +#define CCM_CR_TPM2 17 /* CLOCK Root Tpm2. */ +#define CCM_CR_TPM3 18 /* CLOCK Root Tpm3. */ +#define CCM_CR_TPM4 19 /* CLOCK Root Tpm4. */ +#define CCM_CR_TPM5 20 /* CLOCK Root Tpm5. */ +#define CCM_CR_TPM6 21 /* CLOCK Root Tpm6. */ +#define CCM_CR_FLEXSPI1 22 /* CLOCK Root Flexspi1. */ +#define CCM_CR_CAN1 23 /* CLOCK Root Can1. */ +#define CCM_CR_CAN2 24 /* CLOCK Root Can2. */ +#define CCM_CR_LPUART1 25 /* CLOCK Root Lpuart1. */ +#define CCM_CR_LPUART2 26 /* CLOCK Root Lpuart2. */ +#define CCM_CR_LPUART3 27 /* CLOCK Root Lpuart3. */ +#define CCM_CR_LPUART4 28 /* CLOCK Root Lpuart4. */ +#define CCM_CR_LPUART5 29 /* CLOCK Root Lpuart5. */ +#define CCM_CR_LPUART6 30 /* CLOCK Root Lpuart6. */ +#define CCM_CR_LPUART7 31 /* CLOCK Root Lpuart7. */ +#define CCM_CR_LPUART8 32 /* CLOCK Root Lpuart8. */ +#define CCM_CR_LPI2C1 33 /* CLOCK Root Lpi2c1. */ +#define CCM_CR_LPI2C2 34 /* CLOCK Root Lpi2c2. */ +#define CCM_CR_LPI2C3 35 /* CLOCK Root Lpi2c3. */ +#define CCM_CR_LPI2C4 36 /* CLOCK Root Lpi2c4. */ +#define CCM_CR_LPI2C5 37 /* CLOCK Root Lpi2c5. */ +#define CCM_CR_LPI2C6 38 /* CLOCK Root Lpi2c6. */ +#define CCM_CR_LPI2C7 39 /* CLOCK Root Lpi2c7. */ +#define CCM_CR_LPI2C8 40 /* CLOCK Root Lpi2c8. */ +#define CCM_CR_LPSPI1 41 /* CLOCK Root Lpspi1. */ +#define CCM_CR_LPSPI2 42 /* CLOCK Root Lpspi2. */ +#define CCM_CR_LPSPI3 43 /* CLOCK Root Lpspi3. */ +#define CCM_CR_LPSPI4 44 /* CLOCK Root Lpspi4. */ +#define CCM_CR_LPSPI5 45 /* CLOCK Root Lpspi5. */ +#define CCM_CR_LPSPI6 46 /* CLOCK Root Lpspi6. */ +#define CCM_CR_LPSPI7 47 /* CLOCK Root Lpspi7. */ +#define CCM_CR_LPSPI8 48 /* CLOCK Root Lpspi8. */ +#define CCM_CR_I3C1 49 /* CLOCK Root I3c1. */ +#define CCM_CR_I3C2 50 /* CLOCK Root I3c2. */ +#define CCM_CR_USDHC1 51 /* CLOCK Root Usdhc1. */ +#define CCM_CR_USDHC2 52 /* CLOCK Root Usdhc2. */ +#define CCM_CR_USDHC3 53 /* CLOCK Root Usdhc3. */ +#define CCM_CR_SAI1 54 /* CLOCK Root Sai1. */ +#define CCM_CR_SAI2 55 /* CLOCK Root Sai2. */ +#define CCM_CR_SAI3 56 /* CLOCK Root Sai3. */ +#define CCM_CR_CCMCKO1 57 /* CLOCK Root Ccm Cko1. */ +#define CCM_CR_CCMCKO2 58 /* CLOCK Root Ccm Cko2. */ +#define CCM_CR_CCMCKO3 59 /* CLOCK Root Ccm Cko3. */ +#define CCM_CR_CCMCKO4 60 /* CLOCK Root Ccm Cko4. */ +#define CCM_CR_HSIO 61 /* CLOCK Root Hsio. */ +#define CCM_CR_HSIOUSBTEST60M 62 /* CLOCK Root Hsio Usb Test 60M. */ +#define CCM_CR_HSIOACSCAN80M 63 /* CLOCK Root Hsio Acscan 80M. */ +#define CCM_CR_HSIOACSCAN480M 64 /* CLOCK Root Hsio Acscan 480M. */ +#define CCM_CR_NIC 65 /* CLOCK Root Nic. */ +#define CCM_CR_NICAPB 66 /* CLOCK Root Nic Apb. */ +#define CCM_CR_MLAPB 67 /* CLOCK Root Ml Apb. */ +#define CCM_CR_ML 68 /* CLOCK Root Ml. */ +#define CCM_CR_MEDIAAXI 69 /* CLOCK Root Media Axi. */ +#define CCM_CR_MEDIAAPB 70 /* CLOCK Root Media Apb. */ +#define CCM_CR_MEDIALDB 71 /* CLOCK Root Media Ldb. */ +#define CCM_CR_MEDIADISPPIX 72 /* CLOCK Root Media Disp Pix. */ +#define CCM_CR_CAMPIX 73 /* CLOCK Root Cam Pix. */ +#define CCM_CR_MIPITESTBYTE 74 /* CLOCK Root Mipi Test Byte. */ +#define CCM_CR_MIPIPHYCFG 75 /* CLOCK Root Mipi Phy Cfg. */ +#define CCM_CR_DRAMALT 76 /* CLOCK Root Dram Alt. */ +#define CCM_CR_DRAMAPB 77 /* CLOCK Root Dram Apb. */ +#define CCM_CR_ADC 78 /* CLOCK Root Adc. */ +#define CCM_CR_PDM 79 /* CLOCK Root Pdm. */ +#define CCM_CR_TSTMR1 80 /* CLOCK Root Tstmr1. */ +#define CCM_CR_TSTMR2 81 /* CLOCK Root Tstmr2. */ +#define CCM_CR_MQS1 82 /* CLOCK Root MQS1. */ +#define CCM_CR_MQS2 83 /* CLOCK Root MQS2. */ +#define CCM_CR_AUDIOXCVR 84 /* CLOCK Root Audio XCVR. */ +#define CCM_CR_SPDIF 85 /* CLOCK Root Spdif. */ +#define CCM_CR_ENET 86 /* CLOCK Root Enet. */ +#define CCM_CR_ENETTIMER1 87 /* CLOCK Root Enet Timer1. */ +#define CCM_CR_ENETTIMER2 88 /* CLOCK Root Enet Timer2. */ +#define CCM_CR_ENETREF 89 /* CLOCK Root Enet Ref. */ +#define CCM_CR_ENETREFPHY 90 /* CLOCK Root Enet Ref Phy. */ +#define CCM_CR_I3C1SLOW 91 /* CLOCK Root I3c1Slow. */ +#define CCM_CR_I3C2SLOW 92 /* CLOCK Root I3c2Slow. */ +#define CCM_CR_USBPHYBURUNIN 93 /* CLOCK Root Usb Phy Burunin. */ +#define CCM_CR_PALCAMESCAN 94 /* CLOCK Root Pal Came Scan. */ + +/* Clock gates */ + +#define CCM_LPCG_A55 0 +#define CCM_LPCG_CM33 1 +#define CCM_LPCG_ARM_TROUT 2 +#define CCM_LPCG_SENTINEL 3 +#define CCM_LPCG_SIM_WAKEUP 4 +#define CCM_LPCG_SIM_AON 5 +#define CCM_LPCG_SIM_MEGA 6 +#define CCM_LPCG_ANADIG 7 +#define CCM_LPCG_SRC 8 +#define CCM_LPCG_CCM 9 +#define CCM_LPCG_GPC 10 +#define CCM_LPCG_ADC1 11 +#define CCM_LPCG_WDOG1 12 +#define CCM_LPCG_WDOG2 13 +#define CCM_LPCG_WDOG3 14 +#define CCM_LPCG_WDOG4 15 +#define CCM_LPCG_WDOG5 16 +#define CCM_LPCG_SEMA1 17 +#define CCM_LPCG_SEMA2 18 +#define CCM_LPCG_MU_A 19 +#define CCM_LPCG_MU_B 20 +#define CCM_LPCG_EDMA1 21 +#define CCM_LPCG_EDMA2 22 +#define CCM_LPCG_ROMCP_A55 23 +#define CCM_LPCG_ROMCP_M33 24 +#define CCM_LPCG_FLEXSPI1 25 +#define CCM_LPCG_AON_TRDC 26 +#define CCM_LPCG_WKUP_TRDC 27 +#define CCM_LPCG_OCOTP 28 +#define CCM_LPCG_BBSM_HP 29 +#define CCM_LPCG_BBSM 30 +#define CCM_LPCG_CSTRACE 31 +#define CCM_LPCG_CSSWO 32 +#define CCM_LPCG_IOMUXC 33 +#define CCM_LPCG_GPIO1 34 +#define CCM_LPCG_GPIO2 35 +#define CCM_LPCG_GPIO3 36 +#define CCM_LPCG_GPIO4 37 +#define CCM_LPCG_FLEXIO1 38 +#define CCM_LPCG_FLEXIO2 39 +#define CCM_LPCG_LPIT1 40 +#define CCM_LPCG_LPIT2 41 +#define CCM_LPCG_LPTMR1 42 +#define CCM_LPCG_LPTMR2 43 +#define CCM_LPCG_TPM1 44 +#define CCM_LPCG_TPM2 45 +#define CCM_LPCG_TPM3 46 +#define CCM_LPCG_TPM4 47 +#define CCM_LPCG_TPM5 48 +#define CCM_LPCG_TPM6 49 +#define CCM_LPCG_CAN1 50 +#define CCM_LPCG_CAN2 51 +#define CCM_LPCG_LPUART1 52 +#define CCM_LPCG_LPUART2 53 +#define CCM_LPCG_LPUART3 54 +#define CCM_LPCG_LPUART4 55 +#define CCM_LPCG_LPUART5 56 +#define CCM_LPCG_LPUART6 57 +#define CCM_LPCG_LPUART7 58 +#define CCM_LPCG_LPUART8 59 +#define CCM_LPCG_LPI2C1 60 +#define CCM_LPCG_LPI2C2 61 +#define CCM_LPCG_LPI2C3 62 +#define CCM_LPCG_LPI2C4 63 +#define CCM_LPCG_LPI2C5 64 +#define CCM_LPCG_LPI2C6 65 +#define CCM_LPCG_LPI2C7 66 +#define CCM_LPCG_LPI2C8 67 +#define CCM_LPCG_LPSPI1 68 +#define CCM_LPCG_LPSPI2 69 +#define CCM_LPCG_LPSPI3 70 +#define CCM_LPCG_LPSPI4 71 +#define CCM_LPCG_LPSPI5 72 +#define CCM_LPCG_LPSPI6 73 +#define CCM_LPCG_LPSPI7 74 +#define CCM_LPCG_LPSPI8 75 +#define CCM_LPCG_I3C1 76 +#define CCM_LPCG_I3C2 77 +#define CCM_LPCG_USDHC1 78 +#define CCM_LPCG_USDHC2 79 +#define CCM_LPCG_USDHC3 80 +#define CCM_LPCG_SAI1 81 +#define CCM_LPCG_SAI2 82 +#define CCM_LPCG_SAI3 83 +#define CCM_LPCG_SSI_W2AO 84 +#define CCM_LPCG_SSI_AO2W 85 +#define CCM_LPCG_MIPI_CSI 86 +#define CCM_LPCG_MIPI_DSI 87 +#define CCM_LPCG_LVDS 88 +#define CCM_LPCG_LCDIF 89 +#define CCM_LPCG_PXP 90 +#define CCM_LPCG_ISI 91 +#define CCM_LPCG_NIC_MEDIA 92 +#define CCM_LPCG_DDR_DFI 93 +#define CCM_LPCG_DDR_CTL 94 +#define CCM_LPCG_DDR_DFI_CTL 95 +#define CCM_LPCG_DDR_SSI 96 +#define CCM_LPCG_DDR_BYPASS 97 +#define CCM_LPCG_DDR_APB 98 +#define CCM_LPCG_DDR_DRAMPLL 99 +#define CCM_LPCG_DDR_CLK_CTL 100 +#define CCM_LPCG_NIC_CENTRAL 101 +#define CCM_LPCG_GIC600 102 +#define CCM_LPCG_NIC_APB 103 +#define CCM_LPCG_USB_CONTROLLER 104 +#define CCM_LPCG_USB_TEST_60M 105 +#define CCM_LPCG_HSIO_TROUT_24M 106 +#define CCM_LPCG_PDM 107 +#define CCM_LPCG_MQS1 108 +#define CCM_LPCG_MQS2 109 +#define CCM_LPCG_AUD_XCVR 110 +#define CCM_LPCG_NICMIX_MECC 111 +#define CCM_LPCG_SPDIF 112 +#define CCM_LPCG_SSI_ML2NIC 113 +#define CCM_LPCG_SSI_MED2NIC 114 +#define CCM_LPCG_SSI_HSIO2NIC 115 +#define CCM_LPCG_SSI_W2NIC 116 +#define CCM_LPCG_SSI_NIC2W 117 +#define CCM_LPCG_SSI_NIC2DDR 118 +#define CCM_LPCG_HSIO_32K 119 +#define CCM_LPCG_ENET1 120 +#define CCM_LPCG_ENET_QOS 121 +#define CCM_LPCG_SYS_CNT 122 +#define CCM_LPCG_TSTMR1 123 +#define CCM_LPCG_TSTMR2 124 +#define CCM_LPCG_TMC 125 +#define CCM_LPCG_PMRO 126 + +/* Other parameters */ + +#define ROOT_MUX_MAX 4 /* Count of root clock MUX options */ +#define CCM_CR_COUNT 94 /* Count of clock roots */ +#define CCM_LPCG_COUNT 126 /* Counte of clock gates */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* NOTE: The PLL input (IN) clocks are not available in clock tree */ + +enum ccm_clock_name_e +{ + OSC_24M = 0, /* 24MHZ OSCILLATOR. */ + ARM_PLL = 1, /* ARM PLL */ + ARM_PLLOUT = 2, /* ARM PLL OUT */ + SYS_PLL1_IN = 3, /* SYSTEM PLL1 IN */ + SYS_PLL1PFD0_IN = 4, /* SYSTEM PLL1 PFD0 IN */ + SYS_PLL1PFD0 = 5, /* SYSTEM PLL1 PFD0 */ + SYS_PLL1PFD0DIV2 = 6, /* SYSTEM PLL1 PFD0 DIV2 */ + SYS_PLL1PFD1_IN = 7, /* SYSTEM PLL1 PFD1 IN */ + SYS_PLL1PFD1 = 8, /* SYSTEM PLL1 PFD1 */ + SYS_PLL1PFD1DIV2 = 9, /* SYSTEM PLL1 PFD1 DIV2 */ + SYS_PLL1PFD2_IN = 10, /* SYSTEM PLL1 PFD2 IN */ + SYS_PLL1PFD2 = 11, /* SYSTEM PLL1 PFD2 */ + SYS_PLL1PFD2DIV2 = 12, /* SYSTEM PLL1 PFD2 DIV2 */ + AUDIO_PLL1 = 13, /* AUDIO PLL1 */ + AUDIO_PLL1OUT = 14, /* AUDIO PLL1 OUT */ + DRAM_PLL = 15, /* DRAM PLL */ + DRAM_PLLOUT = 16, /* DRAM PLL OUT */ + VIDEO_PLL1 = 17, /* VIDEO PLL1 */ + VIDEO_PLL1OUT = 18, /* VIDEO PLL1 OUT */ + EXT = 19, /* EXT */ +}; + +/* This contains a simple LUT to find the corresponding MUX index per root */ + +static const int g_ccm_root_mux[][ROOT_MUX_MAX] = +{ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Arm A55 Periph */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Arm A55 MTR BUS */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Arm A55 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* M33 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Sentinel */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Bus Wakeup */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Bus Aon */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Wakeup Axi */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Swo Trace */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* M33 Systick */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Flexio1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Flexio2 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpit1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpit2 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lptmr1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lptmr2 */ + {OSC_24M, SYS_PLL1PFD0, AUDIO_PLL1OUT, EXT}, /* Tpm1 */ + {OSC_24M, SYS_PLL1PFD0, AUDIO_PLL1OUT, EXT}, /* Tpm2 */ + {OSC_24M, SYS_PLL1PFD0, AUDIO_PLL1OUT, EXT}, /* Tpm3 */ + {OSC_24M, SYS_PLL1PFD0, AUDIO_PLL1OUT, EXT}, /* Tpm4 */ + {OSC_24M, SYS_PLL1PFD0, AUDIO_PLL1OUT, EXT}, /* Tpm5 */ + {OSC_24M, SYS_PLL1PFD0, AUDIO_PLL1OUT, EXT}, /* Tpm6 */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Flexspi1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Can1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Can2 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpuart1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpuart2 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpuart3 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpuart4 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpuart5 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpuart6 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpuart7 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpuart8 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpi2c1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpi2c2 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpi2c3 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpi2c4 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpi2c5 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpi2c6 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpi2c7 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpi2c8 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpspi1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpspi2 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpspi3 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpspi4 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpspi5 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpspi6 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpspi7 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Lpspi8 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* I3c1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* I3c2 */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Usdhc1 */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Usdhc2 */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Usdhc3 */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, EXT}, /* Sai1 */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, EXT}, /* Sai2 */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, EXT}, /* Sai3 */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, AUDIO_PLL1OUT}, /* Ccm Cko1 */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, VIDEO_PLL1OUT}, /* Ccm Cko2 */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, AUDIO_PLL1OUT}, /* Ccm Cko3 */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, VIDEO_PLL1OUT}, /* Ccm Cko4 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Hsio */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Hsio Usb Test 60M */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Hsio Acscan 80M */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, SYS_PLL1PFD2}, /* Hsio Acscan 480M */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Nic */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Nic Apb */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Ml Apb */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Ml */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Media Axi */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Media Apb */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, SYS_PLL1PFD0}, /* Media Ldb */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, SYS_PLL1PFD0}, /* Media Disp Pix */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, SYS_PLL1PFD0}, /* Cam Pix */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, SYS_PLL1PFD0}, /* Mipi Test Byte */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, SYS_PLL1PFD0}, /* Mipi Phy Cfg */ + {OSC_24M, SYS_PLL1PFD0, SYS_PLL1PFD1, SYS_PLL1PFD2}, /* Dram Alt */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, SYS_PLL1PFD2DIV2}, /* Dram Apb */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Adc */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, EXT}, /* Pdm */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Tstmr1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Tstmr2 */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, EXT}, /* Mqs1 */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, EXT}, /* Mqs2 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, SYS_PLL1PFD2DIV2}, /* Audio XCVR */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, EXT}, /* Spdif */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, SYS_PLL1PFD2DIV2}, /* Enet */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Enet Timer1 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Enet Timer2 */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, SYS_PLL1PFD2DIV2}, /* Enet Ref */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Enet Ref Phy */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* I3c1 Slow */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* I3c2 Slow */ + {OSC_24M, SYS_PLL1PFD0DIV2, SYS_PLL1PFD1DIV2, VIDEO_PLL1OUT}, /* Usb Phy Burunin */ + {OSC_24M, AUDIO_PLL1OUT, VIDEO_PLL1OUT, SYS_PLL1PFD2}, /* Pal Came Scan */ +}; + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_CCM_H */ diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_gpio.h b/arch/arm64/src/imx9/hardware/imx93/imx93_gpio.h new file mode 100644 index 0000000000000..e00856d6780ac --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_gpio.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx93/imx93_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_GPIO_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "imx93_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMX9_GPIO_VERID_OFFSET (0x0000) /* Version ID */ +#define IMX9_GPIO_PARAM_OFFSET (0x0004) /* Parameter */ +#define IMX9_GPIO_LOCK_OFFSET (0x000c) /* Lock */ +#define IMX9_GPIO_PCNS_OFFSET (0x0010) /* Pin Control Nonsecure */ +#define IMX9_GPIO_ICNS_OFFSET (0x0014) /* Interrupt Control Nonsecure */ +#define IMX9_GPIO_PCNP_OFFSET (0x0018) /* Pin Control Nonprivilege */ +#define IMX9_GPIO_ICNP_OFFSET (0x001c) /* Interrupt Control Nonprivilege */ +#define IMX9_GPIO_PDOR_OFFSET (0x0040) /* Port Data Output */ +#define IMX9_GPIO_PSOR_OFFSET (0x0044) /* Port Set Output */ +#define IMX9_GPIO_PCOR_OFFSET (0x0048) /* Port Clear Output */ +#define IMX9_GPIO_PTOR_OFFSET (0x004c) /* Port Toggle Output */ +#define IMX9_GPIO_PDIR_OFFSET (0x0050) /* Port Data Input */ +#define IMX9_GPIO_PDDR_OFFSET (0x0054) /* Port Data Direction */ +#define IMX9_GPIO_PIDR_OFFSET (0x0058) /* Port Input Disable */ +#define IMX9_GPIO_P0DR_OFFSET (0x0060) /* Pin Data (0-31 at offsets of n * 4h) */ +#define IMX9_GPIO_ICR0_OFFSET (0x0080) /* Interrupt Control (0-31 at offsets of n * 4h) */ +#define IMX9_GPIO_GICLR_OFFSET (0x0100) /* Global Interrupt Control Low */ +#define IMX9_GPIO_GICHR_OFFSET (0x0104) /* Global Interrupt Control High */ +#define IMX9_GPIO_ISFR0_OFFSET (0x0120) /* Interrupt Status Flag */ +#define IMX9_GPIO_ISFR1_OFFSET (0x0124) /* Interrupt Status Flag */ + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_GPIO_H */ diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_iomux.h b/arch/arm64/src/imx9/hardware/imx93/imx93_iomux.h new file mode 100644 index 0000000000000..afa9b388f7832 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_iomux.h @@ -0,0 +1,604 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx93/imx93_iomux.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_IOMUX_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_IOMUX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets */ + +#define IOMUXC_MUX_CTL_DAP_TDI_OFFSET (0x0000) +#define IOMUXC_MUX_CTL_DAP_TMS_SWDIO_OFFSET (0x0004) +#define IOMUXC_MUX_CTL_DAP_TCLK_SWCLK_OFFSET (0x0008) +#define IOMUXC_MUX_CTL_DAP_TDO_TRACESWO_OFFSET (0x000C) +#define IOMUXC_MUX_CTL_GPIO_IO00_OFFSET (0x0010) +#define IOMUXC_MUX_CTL_GPIO_IO01_OFFSET (0x0014) +#define IOMUXC_MUX_CTL_GPIO_IO02_OFFSET (0x0018) +#define IOMUXC_MUX_CTL_GPIO_IO03_OFFSET (0x001C) +#define IOMUXC_MUX_CTL_GPIO_IO04_OFFSET (0x0020) +#define IOMUXC_MUX_CTL_GPIO_IO05_OFFSET (0x0024) +#define IOMUXC_MUX_CTL_GPIO_IO06_OFFSET (0x0028) +#define IOMUXC_MUX_CTL_GPIO_IO07_OFFSET (0x002C) +#define IOMUXC_MUX_CTL_GPIO_IO08_OFFSET (0x0030) +#define IOMUXC_MUX_CTL_GPIO_IO09_OFFSET (0x0034) +#define IOMUXC_MUX_CTL_GPIO_IO10_OFFSET (0x0038) +#define IOMUXC_MUX_CTL_GPIO_IO11_OFFSET (0x003C) +#define IOMUXC_MUX_CTL_GPIO_IO12_OFFSET (0x0040) +#define IOMUXC_MUX_CTL_GPIO_IO13_OFFSET (0x0044) +#define IOMUXC_MUX_CTL_GPIO_IO14_OFFSET (0x0048) +#define IOMUXC_MUX_CTL_GPIO_IO15_OFFSET (0x004C) +#define IOMUXC_MUX_CTL_GPIO_IO16_OFFSET (0x0050) +#define IOMUXC_MUX_CTL_GPIO_IO17_OFFSET (0x0054) +#define IOMUXC_MUX_CTL_GPIO_IO18_OFFSET (0x0058) +#define IOMUXC_MUX_CTL_GPIO_IO19_OFFSET (0x005C) +#define IOMUXC_MUX_CTL_GPIO_IO20_OFFSET (0x0060) +#define IOMUXC_MUX_CTL_GPIO_IO21_OFFSET (0x0064) +#define IOMUXC_MUX_CTL_GPIO_IO22_OFFSET (0x0068) +#define IOMUXC_MUX_CTL_GPIO_IO23_OFFSET (0x006C) +#define IOMUXC_MUX_CTL_GPIO_IO24_OFFSET (0x0070) +#define IOMUXC_MUX_CTL_GPIO_IO25_OFFSET (0x0074) +#define IOMUXC_MUX_CTL_GPIO_IO26_OFFSET (0x0078) +#define IOMUXC_MUX_CTL_GPIO_IO27_OFFSET (0x007C) +#define IOMUXC_MUX_CTL_GPIO_IO28_OFFSET (0x0080) +#define IOMUXC_MUX_CTL_GPIO_IO29_OFFSET (0x0084) +#define IOMUXC_MUX_CTL_CCM_CLKO1_OFFSET (0x0088) +#define IOMUXC_MUX_CTL_CCM_CLKO2_OFFSET (0x008C) +#define IOMUXC_MUX_CTL_CCM_CLKO3_OFFSET (0x0090) +#define IOMUXC_MUX_CTL_CCM_CLKO4_OFFSET (0x0094) +#define IOMUXC_MUX_CTL_ENET1_MDC_OFFSET (0x0098) +#define IOMUXC_MUX_CTL_ENET1_MDIO_OFFSET (0x009C) +#define IOMUXC_MUX_CTL_ENET1_TD3_OFFSET (0x00A0) +#define IOMUXC_MUX_CTL_ENET1_TD2_OFFSET (0x00A4) +#define IOMUXC_MUX_CTL_ENET1_TD1_OFFSET (0x00A8) +#define IOMUXC_MUX_CTL_ENET1_TD0_OFFSET (0x00AC) +#define IOMUXC_MUX_CTL_ENET1_TX_CTL_OFFSET (0x00B0) +#define IOMUXC_MUX_CTL_ENET1_TXC_OFFSET (0x00B4) +#define IOMUXC_MUX_CTL_ENET1_RX_CTL_OFFSET (0x00B8) +#define IOMUXC_MUX_CTL_ENET1_RXC_OFFSET (0x00BC) +#define IOMUXC_MUX_CTL_ENET1_RD0_OFFSET (0x00C0) +#define IOMUXC_MUX_CTL_ENET1_RD1_OFFSET (0x00C4) +#define IOMUXC_MUX_CTL_ENET1_RD2_OFFSET (0x00C8) +#define IOMUXC_MUX_CTL_ENET1_RD3_OFFSET (0x00CC) +#define IOMUXC_MUX_CTL_ENET2_MDC_OFFSET (0x00D0) +#define IOMUXC_MUX_CTL_ENET2_MDIO_OFFSET (0x00D4) +#define IOMUXC_MUX_CTL_ENET2_TD3_OFFSET (0x00D8) +#define IOMUXC_MUX_CTL_ENET2_TD2_OFFSET (0x00DC) +#define IOMUXC_MUX_CTL_ENET2_TD1_OFFSET (0x00E0) +#define IOMUXC_MUX_CTL_ENET2_TD0_OFFSET (0x00E4) +#define IOMUXC_MUX_CTL_ENET2_TX_CTL_OFFSET (0x00E8) +#define IOMUXC_MUX_CTL_ENET2_TXC_OFFSET (0x00EC) +#define IOMUXC_MUX_CTL_ENET2_RX_CTL_OFFSET (0x00F0) +#define IOMUXC_MUX_CTL_ENET2_RXC_OFFSET (0x00F4) +#define IOMUXC_MUX_CTL_ENET2_RD0_OFFSET (0x00F8) +#define IOMUXC_MUX_CTL_ENET2_RD1_OFFSET (0x00FC) +#define IOMUXC_MUX_CTL_ENET2_RD2_OFFSET (0x0100) +#define IOMUXC_MUX_CTL_ENET2_RD3_OFFSET (0x0104) +#define IOMUXC_MUX_CTL_SD1_CLK_OFFSET (0x0108) +#define IOMUXC_MUX_CTL_SD1_CMD_OFFSET (0x010C) +#define IOMUXC_MUX_CTL_SD1_DATA0_OFFSET (0x0110) +#define IOMUXC_MUX_CTL_SD1_DATA1_OFFSET (0x0114) +#define IOMUXC_MUX_CTL_SD1_DATA2_OFFSET (0x0118) +#define IOMUXC_MUX_CTL_SD1_DATA3_OFFSET (0x011C) +#define IOMUXC_MUX_CTL_SD1_DATA4_OFFSET (0x0120) +#define IOMUXC_MUX_CTL_SD1_DATA5_OFFSET (0x0124) +#define IOMUXC_MUX_CTL_SD1_DATA6_OFFSET (0x0128) +#define IOMUXC_MUX_CTL_SD1_DATA7_OFFSET (0x012C) +#define IOMUXC_MUX_CTL_SD1_STROBE_OFFSET (0x0130) +#define IOMUXC_MUX_CTL_SD2_VSELECT_OFFSET (0x0134) +#define IOMUXC_MUX_CTL_SD3_CLK_OFFSET (0x0138) +#define IOMUXC_MUX_CTL_SD3_CMD_OFFSET (0x013C) +#define IOMUXC_MUX_CTL_SD3_DATA0_OFFSET (0x0140) +#define IOMUXC_MUX_CTL_SD3_DATA1_OFFSET (0x0144) +#define IOMUXC_MUX_CTL_SD3_DATA2_OFFSET (0x0148) +#define IOMUXC_MUX_CTL_SD3_DATA3_OFFSET (0x014C) +#define IOMUXC_MUX_CTL_SD2_CD_B_OFFSET (0x0150) +#define IOMUXC_MUX_CTL_SD2_CLK_OFFSET (0x0154) +#define IOMUXC_MUX_CTL_SD2_CMD_OFFSET (0x0158) +#define IOMUXC_MUX_CTL_SD2_DATA0_OFFSET (0x015C) +#define IOMUXC_MUX_CTL_SD2_DATA1_OFFSET (0x0160) +#define IOMUXC_MUX_CTL_SD2_DATA2_OFFSET (0x0164) +#define IOMUXC_MUX_CTL_SD2_DATA3_OFFSET (0x0168) +#define IOMUXC_MUX_CTL_SD2_RESET_B_OFFSET (0x016C) +#define IOMUXC_MUX_CTL_I2C1_SCL_OFFSET (0x0170) +#define IOMUXC_MUX_CTL_I2C1_SDA_OFFSET (0x0174) +#define IOMUXC_MUX_CTL_I2C2_SCL_OFFSET (0x0178) +#define IOMUXC_MUX_CTL_I2C2_SDA_OFFSET (0x017C) +#define IOMUXC_MUX_CTL_UART1_RXD_OFFSET (0x0180) +#define IOMUXC_MUX_CTL_UART1_TXD_OFFSET (0x0184) +#define IOMUXC_MUX_CTL_UART2_RXD_OFFSET (0x0188) +#define IOMUXC_MUX_CTL_UART2_TXD_OFFSET (0x018C) +#define IOMUXC_MUX_CTL_PDM_CLK_OFFSET (0x0190) +#define IOMUXC_MUX_CTL_PDM_BIT_STREAM0_OFFSET (0x0194) +#define IOMUXC_MUX_CTL_PDM_BIT_STREAM1_OFFSET (0x0198) +#define IOMUXC_MUX_CTL_SAI1_TXFS_OFFSET (0x019C) +#define IOMUXC_MUX_CTL_SAI1_TXC_OFFSET (0x01A0) +#define IOMUXC_MUX_CTL_SAI1_TXD0_OFFSET (0x01A4) +#define IOMUXC_MUX_CTL_SAI1_RXD0_OFFSET (0x01A8) +#define IOMUXC_MUX_CTL_WDOG_ANY_OFFSET (0x01AC) + +#define IOMUXC_PAD_CTL_DAP_TDI_OFFSET (0x01B0) +#define IOMUXC_PAD_CTL_DAP_TMS_SWDIO_OFFSET (0x01B4) +#define IOMUXC_PAD_CTL_DAP_TCLK_SWCLK_OFFSET (0x01B8) +#define IOMUXC_PAD_CTL_DAP_TDO_TRACESWO_OFFSET (0x01BC) +#define IOMUXC_PAD_CTL_GPIO_IO00_OFFSET (0x01C0) +#define IOMUXC_PAD_CTL_GPIO_IO01_OFFSET (0x01C4) +#define IOMUXC_PAD_CTL_GPIO_IO02_OFFSET (0x01C8) +#define IOMUXC_PAD_CTL_GPIO_IO03_OFFSET (0x01CC) +#define IOMUXC_PAD_CTL_GPIO_IO04_OFFSET (0x01D0) +#define IOMUXC_PAD_CTL_GPIO_IO05_OFFSET (0x01D4) +#define IOMUXC_PAD_CTL_GPIO_IO06_OFFSET (0x01D8) +#define IOMUXC_PAD_CTL_GPIO_IO07_OFFSET (0x01DC) +#define IOMUXC_PAD_CTL_GPIO_IO08_OFFSET (0x01E0) +#define IOMUXC_PAD_CTL_GPIO_IO09_OFFSET (0x01E4) +#define IOMUXC_PAD_CTL_GPIO_IO10_OFFSET (0x01E8) +#define IOMUXC_PAD_CTL_GPIO_IO11_OFFSET (0x01EC) +#define IOMUXC_PAD_CTL_GPIO_IO12_OFFSET (0x01F0) +#define IOMUXC_PAD_CTL_GPIO_IO13_OFFSET (0x01F4) +#define IOMUXC_PAD_CTL_GPIO_IO14_OFFSET (0x01F8) +#define IOMUXC_PAD_CTL_GPIO_IO15_OFFSET (0x01FC) +#define IOMUXC_PAD_CTL_GPIO_IO16_OFFSET (0x0200) +#define IOMUXC_PAD_CTL_GPIO_IO17_OFFSET (0x0204) +#define IOMUXC_PAD_CTL_GPIO_IO18_OFFSET (0x0208) +#define IOMUXC_PAD_CTL_GPIO_IO19_OFFSET (0x020C) +#define IOMUXC_PAD_CTL_GPIO_IO20_OFFSET (0x0210) +#define IOMUXC_PAD_CTL_GPIO_IO21_OFFSET (0x0214) +#define IOMUXC_PAD_CTL_GPIO_IO22_OFFSET (0x0218) +#define IOMUXC_PAD_CTL_GPIO_IO23_OFFSET (0x021C) +#define IOMUXC_PAD_CTL_GPIO_IO24_OFFSET (0x0220) +#define IOMUXC_PAD_CTL_GPIO_IO25_OFFSET (0x0224) +#define IOMUXC_PAD_CTL_GPIO_IO26_OFFSET (0x0228) +#define IOMUXC_PAD_CTL_GPIO_IO27_OFFSET (0x022C) +#define IOMUXC_PAD_CTL_GPIO_IO28_OFFSET (0x0230) +#define IOMUXC_PAD_CTL_GPIO_IO29_OFFSET (0x0234) +#define IOMUXC_PAD_CTL_CCM_CLKO1_OFFSET (0x0238) +#define IOMUXC_PAD_CTL_CCM_CLKO2_OFFSET (0x023C) +#define IOMUXC_PAD_CTL_CCM_CLKO3_OFFSET (0x0240) +#define IOMUXC_PAD_CTL_CCM_CLKO4_OFFSET (0x0244) +#define IOMUXC_PAD_CTL_ENET1_MDC_OFFSET (0x0248) +#define IOMUXC_PAD_CTL_ENET1_MDIO_OFFSET (0x024C) +#define IOMUXC_PAD_CTL_ENET1_TD3_OFFSET (0x0250) +#define IOMUXC_PAD_CTL_ENET1_TD2_OFFSET (0x0254) +#define IOMUXC_PAD_CTL_ENET1_TD1_OFFSET (0x0258) +#define IOMUXC_PAD_CTL_ENET1_TD0_OFFSET (0x025C) +#define IOMUXC_PAD_CTL_ENET1_TX_CTL_OFFSET (0x0260) +#define IOMUXC_PAD_CTL_ENET1_TXC_OFFSET (0x0264) +#define IOMUXC_PAD_CTL_ENET1_RX_CTL_OFFSET (0x0268) +#define IOMUXC_PAD_CTL_ENET1_RXC_OFFSET (0x026C) +#define IOMUXC_PAD_CTL_ENET1_RD0_OFFSET (0x0270) +#define IOMUXC_PAD_CTL_ENET1_RD1_OFFSET (0x0274) +#define IOMUXC_PAD_CTL_ENET1_RD2_OFFSET (0x0278) +#define IOMUXC_PAD_CTL_ENET1_RD3_OFFSET (0x027C) +#define IOMUXC_PAD_CTL_ENET2_MDC_OFFSET (0x0280) +#define IOMUXC_PAD_CTL_ENET2_MDIO_OFFSET (0x0284) +#define IOMUXC_PAD_CTL_ENET2_TD3_OFFSET (0x0288) +#define IOMUXC_PAD_CTL_ENET2_TD2_OFFSET (0x028C) +#define IOMUXC_PAD_CTL_ENET2_TD1_OFFSET (0x01B0) +#define IOMUXC_PAD_CTL_ENET2_TD0_OFFSET (0x01B0) +#define IOMUXC_PAD_CTL_ENET2_TX_CTL_OFFSET (0x01B0) +#define IOMUXC_PAD_CTL_ENET2_TXC_OFFSET (0x029C) +#define IOMUXC_PAD_CTL_ENET2_RX_CTL_OFFSET (0x02A0) +#define IOMUXC_PAD_CTL_ENET2_RXC_OFFSET (0x02A4) +#define IOMUXC_PAD_CTL_ENET2_RD0_OFFSET (0x02A8) +#define IOMUXC_PAD_CTL_ENET2_RD1_OFFSET (0x02AC) +#define IOMUXC_PAD_CTL_ENET2_RD2_OFFSET (0x02B0) +#define IOMUXC_PAD_CTL_ENET2_RD3_OFFSET (0x02B4) +#define IOMUXC_PAD_CTL_SD1_CLK_OFFSET (0x02B8) +#define IOMUXC_PAD_CTL_SD1_CMD_OFFSET (0x02BC) +#define IOMUXC_PAD_CTL_SD1_DATA0_OFFSET (0x02C0) +#define IOMUXC_PAD_CTL_SD1_DATA1_OFFSET (0x02C4) +#define IOMUXC_PAD_CTL_SD1_DATA2_OFFSET (0x02C8) +#define IOMUXC_PAD_CTL_SD1_DATA3_OFFSET (0x02CC) +#define IOMUXC_PAD_CTL_SD1_DATA4_OFFSET (0x02D0) +#define IOMUXC_PAD_CTL_SD1_DATA5_OFFSET (0x02D4) +#define IOMUXC_PAD_CTL_SD1_DATA6_OFFSET (0x02D8) +#define IOMUXC_PAD_CTL_SD1_DATA7_OFFSET (0x02DC) +#define IOMUXC_PAD_CTL_SD1_STROBE_OFFSET (0x02E0) +#define IOMUXC_PAD_CTL_SD2_VSELECT_OFFSET (0x02E4) +#define IOMUXC_PAD_CTL_SD3_CLK_OFFSET (0x02E8) +#define IOMUXC_PAD_CTL_SD3_CMD_OFFSET (0x02EC) +#define IOMUXC_PAD_CTL_SD3_DATA0_OFFSET (0x02F0) +#define IOMUXC_PAD_CTL_SD3_DATA1_OFFSET (0x02F4) +#define IOMUXC_PAD_CTL_SD3_DATA2_OFFSET (0x02F8) +#define IOMUXC_PAD_CTL_SD3_DATA3_OFFSET (0x02FC) +#define IOMUXC_PAD_CTL_SD2_CD_B_OFFSET (0x0300) +#define IOMUXC_PAD_CTL_SD2_CLK_OFFSET (0x0304) +#define IOMUXC_PAD_CTL_SD2_CMD_OFFSET (0x0308) +#define IOMUXC_PAD_CTL_SD2_DATA0_OFFSET (0x030C) +#define IOMUXC_PAD_CTL_SD2_DATA1_OFFSET (0x0310) +#define IOMUXC_PAD_CTL_SD2_DATA2_OFFSET (0x0314) +#define IOMUXC_PAD_CTL_SD2_DATA3_OFFSET (0x0318) +#define IOMUXC_PAD_CTL_SD2_RESET_B_OFFSET (0x031C) +#define IOMUXC_PAD_CTL_I2C1_SCL_OFFSET (0x0320) +#define IOMUXC_PAD_CTL_I2C1_SDA_OFFSET (0x0324) +#define IOMUXC_PAD_CTL_I2C2_SCL_OFFSET (0x0328) +#define IOMUXC_PAD_CTL_I2C2_SDA_OFFSET (0x032C) +#define IOMUXC_PAD_CTL_UART1_RXD_OFFSET (0x0330) +#define IOMUXC_PAD_CTL_UART1_TXD_OFFSET (0x0334) +#define IOMUXC_PAD_CTL_UART2_RXD_OFFSET (0x0338) +#define IOMUXC_PAD_CTL_UART2_TXD_OFFSET (0x033C) +#define IOMUXC_PAD_CTL_PDM_CLK_OFFSET (0x0340) +#define IOMUXC_PAD_CTL_PDM_BIT_STREAM0_OFFSET (0x0344) +#define IOMUXC_PAD_CTL_PDM_BIT_STREAM1_OFFSET (0x0348) +#define IOMUXC_PAD_CTL_SAI1_TXFS_OFFSET (0x034C) +#define IOMUXC_PAD_CTL_SAI1_TXC_OFFSET (0x0350) +#define IOMUXC_PAD_CTL_SAI1_TXD0_OFFSET (0x0354) +#define IOMUXC_PAD_CTL_SAI1_RXD0_OFFSET (0x0358) +#define IOMUXC_PAD_CTL_WDOG_ANY_OFFSET (0x035C) + +#define CAN1_IPP_IND_CANRX_SELECT_INPUT_OFFSET (0x0360) +#define CAN2_IPP_IND_CANRX_SELECT_INPUT_OFFSET (0x0364) +#define CCMSRCGPCMIX_EXT1_CLK_SELECT_INPUT_OFFSET (0x0368) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_0_OFFSET (0x036C) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_1_OFFSET (0x0370) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_2_OFFSET (0x0374) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_3_OFFSET (0x0378) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_4_OFFSET (0x037C) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_5_OFFSET (0x0380) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_6_OFFSET (0x0384) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_7_OFFSET (0x0388) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_8_OFFSET (0x038C) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_9_OFFSET (0x0390) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_10_OFFSET (0x0394) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_11_OFFSET (0x0398) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_13_OFFSET (0x039C) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_14_OFFSET (0x03A0) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_15_OFFSET (0x03A4) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_16_OFFSET (0x03A8) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_17_OFFSET (0x03AC) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_18_OFFSET (0x03B0) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_20_OFFSET (0x03B4) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_22_OFFSET (0x03B8) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_23_OFFSET (0x03BC) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_24_OFFSET (0x03C0) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_25_OFFSET (0x03C4) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_27_OFFSET (0x03C8) +#define I3C2_PIN_SCL_IN_SELECT_INPUT_OFFSET (0x03CC) +#define I3C2_PIN_SDA_IN_SELECT_INPUT_OFFSET (0x03D0) +#define JTAG_MUX_TCK_SELECT_INPUT_OFFSET (0x03D4) +#define JTAG_MUX_TDI_SELECT_INPUT_OFFSET (0x03D8) +#define JTAG_MUX_TMS_SELECT_INPUT_OFFSET (0x03DC) +#define LP12C3_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET (0x03E0) +#define LPI12C3_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET (0x03E4) +#define LP12C5_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET (0x03E8) +#define LP12C5_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET (0x03EC) +#define LPI2C6_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET (0x03F0) +#define LPI2C6_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET (0x03F4) +#define LPI2C7_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET (0x03F8) +#define LPI2C7_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET (0x03FC) +#define LPI2C8_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET (0x0400) +#define LPI2C8_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET (0x0404) +#define LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_O_OFFSET (0x0408) +#define LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_1_OFFSET (0x040C) +#define LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_2_OFFSET (0x0410) +#define LPUART3_IPP_IND_LPUART_CTS_N_SELECT_INP_OFFSET (0x0414) +#define LPUART3_IPP_IND_LPUART_RXD_SELECT_INPUT_OFFSET (0x0418) +#define LPUART3_IPP_IND_LPUART_TXD_SELECT_INPUT_OFFSET (0x041C) +#define LPUART4_IPP_IND_LPUART_CTS_N_SELECT_INP_OFFSET (0x0420) +#define LPUART4_IPP_IND_LPUART_RXD_SELECT_INPUT_OFFSET (0x0424) +#define LPUART4_IPP_IND_LPUART_TXD_SELECT_INPUT_OFFSET (0x0428) +#define LPUARTS_IPP_IND_LPUART_CTS_N_SELECT_INP_OFFSET (0x042C) +#define LPUARTS_IPP_IND_LPUART_RXD_SELECT_INPUT_OFFSET (0x0430) +#define LPUARTS_IPP_IND_LPUART_TXD_SELECT_INPUT_OFFSET (0x0434) +#define SAI1_IPP_IND_SAI_MCLK_SELECT_INPUT_OFFSET (0x0448) +#define SAI3_IPP_IND_SAI_RXBCLK_SELECT_INPUT_OFFSET (0x044c) +#define SAI3_IPP_IND_SAI_RXSYNC_SELECT_INPUT_OFFSET (0x0450) +#define SPDIF_SPDIF_I_SELECT_INPUT_OFFSET (0x0454) +#define USDHC3_IPP_CARD_CLK_IN_SELECT_INPUT_OFFSET (0x0458) +#define USDHC3_IPP_CMD_IN_SELECT_INPUT_OFFSET (0x045C) +#define USDHC3_IPP_DATO_IN_SELECT_INPUT_OFFSET (0x0460) +#define USDHC3_IPP_DAT1_IN_SELECT_INPUT_OFFSET (0x0464) +#define USDHC3_IPP_DAT2_IN_SELECT_INPUT_OFFSET (0x0468) +#define USDHC3_IPP_DAT3_IN_SELECT_INPUT_OFFSET (0x046C) + +/* Register addresses */ + +#define IOMUXC_MUX_CTL_DAP_TDI (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_DAP_TDI_OFFSET) +#define IOMUXC_MUX_CTL_DAP_TMS_SWDIO (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_DAP_TMS_SWDIO_OFFSET) +#define IOMUXC_MUX_CTL_DAP_TCLK_SWCLK (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_DAP_TCLK_SWCLK_OFFSET) +#define IOMUXC_MUX_CTL_DAP_TDO_TRACESWO (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_DAP_TDO_TRACESWO_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO00 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO00_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO01 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO01_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO02 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO02_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO03 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO03_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO04 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO04_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO05 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO05_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO06 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO06_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO07 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO07_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO08 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO08_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO09 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO09_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO10 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO10_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO11 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO11_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO12 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO12_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO13 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO13_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO14 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO14_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO15 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO15_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO16 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO16_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO17 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO17_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO18 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO18_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO19 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO19_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO20 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO20_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO21 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO21_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO22 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO22_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO23 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO23_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO24 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO24_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO25 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO25_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO26 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO26_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO27 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO27_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO28 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO28_OFFSET) +#define IOMUXC_MUX_CTL_GPIO_IO29 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_GPIO_IO29_OFFSET) +#define IOMUXC_MUX_CTL_CCM_CLKO1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_CCM_CLKO1_OFFSET) +#define IOMUXC_MUX_CTL_CCM_CLKO2 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_CCM_CLKO2_OFFSET) +#define IOMUXC_MUX_CTL_CCM_CLKO3 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_CCM_CLKO3_OFFSET) +#define IOMUXC_MUX_CTL_CCM_CLKO4 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_CCM_CLKO4_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_MDC (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_MDC_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_MDIO (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_MDIO_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_TD3 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_TD3_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_TD2 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_TD2_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_TD1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_TD1_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_TD0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_TD0_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_TX_CTL (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_TX_CTL_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_TXC (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_TXC_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_RX_CTL (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_RX_CTL_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_RXC (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_RXC_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_RD0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_RD0_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_RD1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_RD1_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_RD2 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_RD2_OFFSET) +#define IOMUXC_MUX_CTL_ENET1_RD3 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET1_RD3_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_MDC (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_MDC_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_MDIO (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_MDIO_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_TD3 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_TD3_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_TD2 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_TD2_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_TD1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_TD1_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_TD0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_TD0_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_TX_CTL (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_TX_CTL_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_TXC (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_TXC_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_RX_CTL (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_RX_CTL_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_RXC (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_RXC_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_RD0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_RD0_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_RD1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_RD1_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_RD2 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_RD2_OFFSET) +#define IOMUXC_MUX_CTL_ENET2_RD3 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_ENET2_RD3_OFFSET) +#define IOMUXC_MUX_CTL_SD1_CLK (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_CLK_OFFSET) +#define IOMUXC_MUX_CTL_SD1_CMD (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_CMD_OFFSET) +#define IOMUXC_MUX_CTL_SD1_DATA0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_DATA0_OFFSET) +#define IOMUXC_MUX_CTL_SD1_DATA1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_DATA1_OFFSET) +#define IOMUXC_MUX_CTL_SD1_DATA2 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_DATA2_OFFSET) +#define IOMUXC_MUX_CTL_SD1_DATA3 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_DATA3_OFFSET) +#define IOMUXC_MUX_CTL_SD1_DATA4 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_DATA4_OFFSET) +#define IOMUXC_MUX_CTL_SD1_DATA5 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_DATA5_OFFSET) +#define IOMUXC_MUX_CTL_SD1_DATA6 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_DATA6_OFFSET) +#define IOMUXC_MUX_CTL_SD1_DATA7 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_DATA7_OFFSET) +#define IOMUXC_MUX_CTL_SD1_STROBE (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD1_STROBE_OFFSET) +#define IOMUXC_MUX_CTL_SD2_VSELECT (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_VSELECT_OFFSET) +#define IOMUXC_MUX_CTL_SD3_CLK (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD3_CLK_OFFSET) +#define IOMUXC_MUX_CTL_SD3_CMD (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD3_CMD_OFFSET) +#define IOMUXC_MUX_CTL_SD3_DATA0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD3_DATA0_OFFSET) +#define IOMUXC_MUX_CTL_SD3_DATA1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD3_DATA1_OFFSET) +#define IOMUXC_MUX_CTL_SD3_DATA2 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD3_DATA2_OFFSET) +#define IOMUXC_MUX_CTL_SD3_DATA3 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD3_DATA3_OFFSET) +#define IOMUXC_MUX_CTL_SD2_CD_B (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_CD_B_OFFSET) +#define IOMUXC_MUX_CTL_SD2_CLK (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_CLK_OFFSET) +#define IOMUXC_MUX_CTL_SD2_CMD (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_CMD_OFFSET) +#define IOMUXC_MUX_CTL_SD2_DATA0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_DATA0_OFFSET) +#define IOMUXC_MUX_CTL_SD2_DATA1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_DATA1_OFFSET) +#define IOMUXC_MUX_CTL_SD2_DATA2 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_DATA2_OFFSET) +#define IOMUXC_MUX_CTL_SD2_DATA3 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_DATA3_OFFSET) +#define IOMUXC_MUX_CTL_SD2_RESET_B (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SD2_RESET_B_OFFSET) +#define IOMUXC_MUX_CTL_I2C1_SCL (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_I2C1_SCL_OFFSET) +#define IOMUXC_MUX_CTL_I2C1_SDA (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_I2C1_SDA_OFFSET) +#define IOMUXC_MUX_CTL_I2C2_SCL (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_I2C2_SCL_OFFSET) +#define IOMUXC_MUX_CTL_I2C2_SDA (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_I2C2_SDA_OFFSET) +#define IOMUXC_MUX_CTL_UART1_RXD (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_UART1_RXD_OFFSET) +#define IOMUXC_MUX_CTL_UART1_TXD (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_UART1_TXD_OFFSET) +#define IOMUXC_MUX_CTL_UART2_RXD (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_UART2_RXD_OFFSET) +#define IOMUXC_MUX_CTL_UART2_TXD (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_UART2_TXD_OFFSET) +#define IOMUXC_MUX_CTL_PDM_CLK (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_PDM_CLK_OFFSET) +#define IOMUXC_MUX_CTL_PDM_BIT_STREAM0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_PDM_BIT_STREAM0_OFFSET) +#define IOMUXC_MUX_CTL_PDM_BIT_STREAM1 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_PDM_BIT_STREAM1_OFFSET) +#define IOMUXC_MUX_CTL_SAI1_TXFS (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SAI1_TXFS_OFFSET) +#define IOMUXC_MUX_CTL_SAI1_TXC (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SAI1_TXC_OFFSET) +#define IOMUXC_MUX_CTL_SAI1_TXD0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SAI1_TXD0_OFFSET) +#define IOMUXC_MUX_CTL_SAI1_RXD0 (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_SAI1_RXD0_OFFSET) +#define IOMUXC_MUX_CTL_WDOG_ANY (IMX9_IOMUXC1_BASE + IOMUXC_MUX_CTL_WDOG_ANY_OFFSET) + +#define IOMUXC_PAD_CTL_DAP_TDI (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_DAP_TDI_OFFSET) +#define IOMUXC_PAD_CTL_DAP_TMS_SWDIO (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_DAP_TMS_SWDIO_OFFSET) +#define IOMUXC_PAD_CTL_DAP_TCLK_SWCLK (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_DAP_TCLK_SWCLK_OFFSET) +#define IOMUXC_PAD_CTL_DAP_TDO_TRACESWO (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_DAP_TDO_TRACESWO_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO00 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO00_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO01 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO01_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO02 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO02_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO03 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO03_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO04 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO04_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO05 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO05_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO06 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO06_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO07 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO07_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO08 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO08_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO09 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO09_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO10 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO10_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO11 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO11_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO12 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO12_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO13 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO13_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO14 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO14_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO15 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO15_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO16 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO16_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO17 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO17_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO18 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO18_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO19 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO19_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO20 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO20_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO21 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO21_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO22 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO22_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO23 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO23_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO24 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO24_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO25 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO25_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO26 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO26_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO27 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO27_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO28 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO28_OFFSET) +#define IOMUXC_PAD_CTL_GPIO_IO29 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_GPIO_IO29_OFFSET) +#define IOMUXC_PAD_CTL_CCM_CLKO1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_CCM_CLKO1_OFFSET) +#define IOMUXC_PAD_CTL_CCM_CLKO2 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_CCM_CLKO2_OFFSET) +#define IOMUXC_PAD_CTL_CCM_CLKO3 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_CCM_CLKO3_OFFSET) +#define IOMUXC_PAD_CTL_CCM_CLKO4 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_CCM_CLKO4_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_MDC (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_MDC_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_MDIO (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_MDIO_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_TD3 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_TD3_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_TD2 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_TD2_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_TD1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_TD1_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_TD0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_TD0_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_TX_CTL (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_TX_CTL_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_TXC (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_TXC_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_RX_CTL (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_RX_CTL_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_RXC (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_RXC_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_RD0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_RD0_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_RD1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_RD1_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_RD2 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_RD2_OFFSET) +#define IOMUXC_PAD_CTL_ENET1_RD3 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET1_RD3_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_MDC (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_MDC_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_MDIO (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_MDIO_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_TD3 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_TD3_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_TD2 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_TD2_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_TD1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_TD1_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_TD0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_TD0_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_TX_CTL (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_TX_CTL_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_TXC (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_TXC_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_RX_CTL (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_RX_CTL_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_RXC (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_RXC_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_RD0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_RD0_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_RD1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_RD1_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_RD2 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_RD2_OFFSET) +#define IOMUXC_PAD_CTL_ENET2_RD3 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_ENET2_RD3_OFFSET) +#define IOMUXC_PAD_CTL_SD1_CLK (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_CLK_OFFSET) +#define IOMUXC_PAD_CTL_SD1_CMD (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_CMD_OFFSET) +#define IOMUXC_PAD_CTL_SD1_DATA0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_DATA0_OFFSET) +#define IOMUXC_PAD_CTL_SD1_DATA1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_DATA1_OFFSET) +#define IOMUXC_PAD_CTL_SD1_DATA2 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_DATA2_OFFSET) +#define IOMUXC_PAD_CTL_SD1_DATA3 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_DATA3_OFFSET) +#define IOMUXC_PAD_CTL_SD1_DATA4 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_DATA4_OFFSET) +#define IOMUXC_PAD_CTL_SD1_DATA5 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_DATA5_OFFSET) +#define IOMUXC_PAD_CTL_SD1_DATA6 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_DATA6_OFFSET) +#define IOMUXC_PAD_CTL_SD1_DATA7 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_DATA7_OFFSET) +#define IOMUXC_PAD_CTL_SD1_STROBE (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD1_STROBE_OFFSET) +#define IOMUXC_PAD_CTL_SD2_VSELECT (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_VSELECT_OFFSET) +#define IOMUXC_PAD_CTL_SD3_CLK (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD3_CLK_OFFSET) +#define IOMUXC_PAD_CTL_SD3_CMD (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD3_CMD_OFFSET) +#define IOMUXC_PAD_CTL_SD3_DATA0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD3_DATA0_OFFSET) +#define IOMUXC_PAD_CTL_SD3_DATA1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD3_DATA1_OFFSET) +#define IOMUXC_PAD_CTL_SD3_DATA2 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD3_DATA2_OFFSET) +#define IOMUXC_PAD_CTL_SD3_DATA3 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD3_DATA3_OFFSET) +#define IOMUXC_PAD_CTL_SD2_CD_B (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_CD_B_OFFSET) +#define IOMUXC_PAD_CTL_SD2_CLK (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_CLK_OFFSET) +#define IOMUXC_PAD_CTL_SD2_CMD (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_CMD_OFFSET) +#define IOMUXC_PAD_CTL_SD2_DATA0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_DATA0_OFFSET) +#define IOMUXC_PAD_CTL_SD2_DATA1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_DATA1_OFFSET) +#define IOMUXC_PAD_CTL_SD2_DATA2 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_DATA2_OFFSET) +#define IOMUXC_PAD_CTL_SD2_DATA3 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_DATA3_OFFSET) +#define IOMUXC_PAD_CTL_SD2_RESET_B (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SD2_RESET_B_OFFSET) +#define IOMUXC_PAD_CTL_I2C1_SCL (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_I2C1_SCL_OFFSET) +#define IOMUXC_PAD_CTL_I2C1_SDA (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_I2C1_SDA_OFFSET) +#define IOMUXC_PAD_CTL_I2C2_SCL (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_I2C2_SCL_OFFSET) +#define IOMUXC_PAD_CTL_I2C2_SDA (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_I2C2_SDA_OFFSET) +#define IOMUXC_PAD_CTL_UART1_RXD (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_UART1_RXD_OFFSET) +#define IOMUXC_PAD_CTL_UART1_TXD (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_UART1_TXD_OFFSET) +#define IOMUXC_PAD_CTL_UART2_RXD (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_UART2_RXD_OFFSET) +#define IOMUXC_PAD_CTL_UART2_TXD (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_UART2_TXD_OFFSET) +#define IOMUXC_PAD_CTL_PDM_CLK (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_PDM_CLK_OFFSET) +#define IOMUXC_PAD_CTL_PDM_BIT_STREAM0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_PDM_BIT_STREAM0_OFFSET) +#define IOMUXC_PAD_CTL_PDM_BIT_STREAM1 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_PDM_BIT_STREAM1_OFFSET) +#define IOMUXC_PAD_CTL_SAI1_TXFS (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SAI1_TXFS_OFFSET) +#define IOMUXC_PAD_CTL_SAI1_TXC (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SAI1_TXC_OFFSET) +#define IOMUXC_PAD_CTL_SAI1_TXD0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SAI1_TXD0_OFFSET) +#define IOMUXC_PAD_CTL_SAI1_RXD0 (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_SAI1_RXD0_OFFSET) +#define IOMUXC_PAD_CTL_WDOG_ANY (IMX9_IOMUXC1_BASE + IOMUXC_PAD_CTL_WDOG_ANY_OFFSET) + +#define CAN1_IPP_IND_CANRX_SELECT_INPUT (IMX9_IOMUXC1_BASE + CAN1_IPP_IND_CANRX_SELECT_INPUT_OFFSET) +#define CAN2_IPP_IND_CANRX_SELECT_INPUT (IMX9_IOMUXC1_BASE + CAN2_IPP_IND_CANRX_SELECT_INPUT_OFFSET) +#define CCMSRCGPCMIX_EXT1_CLK_SELECT_INPUT (IMX9_IOMUXC1_BASE + CCMSRCGPCMIX_EXT1_CLK_SELECT_INPUT_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_0 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_0_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_1 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_1_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_2 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_2_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_3 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_3_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_4 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_4_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_5 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_5_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_6 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_6_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_7 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_7_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_8 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_8_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_9 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_9_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_10 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_10_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_11 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_11_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_13 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_13_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_14 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_14_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_15 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_15_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_16 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_16_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_17 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_17_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_18 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_18_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_20 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_20_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_22 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_22_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_23 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_23_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_24 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_24_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_25 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_25_OFFSET) +#define FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_27 (IMX9_IOMUXC1_BASE + FLEXIO1_IPP_IND_FLEXIO_SELECT_INPUT_27_OFFSET) +#define I3C2_PIN_SCL_IN_SELECT_INPUT (IMX9_IOMUXC1_BASE + 13C2_PIN_SCL_IN_SELECT_INPUT_OFFSET) +#define I3C2_PIN_SDA_IN_SELECT_INPUT (IMX9_IOMUXC1_BASE + 13C2_PIN_SDA_IN_SELECT_INPUT_OFFSET) +#define JTAG_MUX_TCK_SELECT_INPUT (IMX9_IOMUXC1_BASE + JTAG_MUX_TCK_SELECT_INPUT_OFFSET) +#define JTAG_MUX_TDI_SELECT_INPUT (IMX9_IOMUXC1_BASE + JTAG_MUX_TDI_SELECT_INPUT_OFFSET) +#define JTAG_MUX_TMS_SELECT_INPUT (IMX9_IOMUXC1_BASE + JTAG_MUX_TMS_SELECT_INPUT_OFFSET) +#define LP12C3_IPP_IND_LPI2C_SCL_SELECT_INPUT (IMX9_IOMUXC1_BASE + LP12C3_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET) +#define LPI12C3_IPP_IND_LPI2C_SDA_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPI12C3_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET) +#define LP12C5_IPP_IND_LPI2C_SCL_SELECT_INPUT (IMX9_IOMUXC1_BASE + LP12C5_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET) +#define LP12C5_IPP_IND_LPI2C_SDA_SELECT_INPUT (IMX9_IOMUXC1_BASE + LP12C5_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET) +#define LPI2C6_IPP_IND_LPI2C_SCL_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPI2C6_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET) +#define LPI2C6_IPP_IND_LPI2C_SDA_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPI2C6_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET) +#define LPI2C7_IPP_IND_LPI2C_SCL_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPI2C7_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET) +#define LPI2C7_IPP_IND_LPI2C_SDA_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPI2C7_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET) +#define LPI2C8_IPP_IND_LPI2C_SCL_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPI2C8_IPP_IND_LPI2C_SCL_SELECT_INPUT_OFFSET) +#define LPI2C8_IPP_IND_LPI2C_SDA_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPI2C8_IPP_IND_LPI2C_SDA_SELECT_INPUT_OFFSET) +#define LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_O (IMX9_IOMUXC1_BASE + LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_O_OFFSET) +#define LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_1 (IMX9_IOMUXC1_BASE + LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_1_OFFSET) +#define LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_2 (IMX9_IOMUXC1_BASE + LPTMR2_IPP_IND_LPTIMER_SELECT_INPUT_2_OFFSET) +#define LPUART3_IPP_IND_LPUART_CTS_N_SELECT_INP (IMX9_IOMUXC1_BASE + LPUART3_IPP_IND_LPUART_CTS_N_SELECT_INP_OFFSET) +#define LPUART3_IPP_IND_LPUART_RXD_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPUART3_IPP_IND_LPUART_RXD_SELECT_INPUT_OFFSET) +#define LPUART3_IPP_IND_LPUART_TXD_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPUART3_IPP_IND_LPUART_TXD_SELECT_INPUT_OFFSET) +#define LPUART4_IPP_IND_LPUART_CTS_N_SELECT_INP (IMX9_IOMUXC1_BASE + LPUART4_IPP_IND_LPUART_CTS_N_SELECT_INP_OFFSET) +#define LPUART4_IPP_IND_LPUART_RXD_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPUART4_IPP_IND_LPUART_RXD_SELECT_INPUT_OFFSET) +#define LPUART4_IPP_IND_LPUART_TXD_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPUART4_IPP_IND_LPUART_TXD_SELECT_INPUT_OFFSET) +#define LPUARTS_IPP_IND_LPUART_CTS_N_SELECT_INP (IMX9_IOMUXC1_BASE + LPUARTS_IPP_IND_LPUART_CTS_N_SELECT_INP_OFFSET) +#define LPUARTS_IPP_IND_LPUART_RXD_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPUARTS_IPP_IND_LPUART_RXD_SELECT_INPUT_OFFSET) +#define LPUARTS_IPP_IND_LPUART_TXD_SELECT_INPUT (IMX9_IOMUXC1_BASE + LPUARTS_IPP_IND_LPUART_TXD_SELECT_INPUT_OFFSET) +#define SAI1_IPP_IND_SAI_MCLK_SELECT_INPUT (IMX9_IOMUXC1_BASE + SAI1_IPP_IND_SAI_MCLK_SELECT_INPUT_OFFSET) +#define SAI3_IPP_IND_SAI_RXBCLK_SELECT_INPUT (IMX9_IOMUXC1_BASE + SAI3_IPP_IND_SAI_RXBCLK_SELECT_INPUT_OFFSET) +#define SAI3_IPP_IND_SAI_RXSYNC_SELECT_INPUT (IMX9_IOMUXC1_BASE + SAI3_IPP_IND_SAI_RXSYNC_SELECT_INPUT_OFFSET) +#define SPDIF_SPDIF_I_SELECT_INPUT (IMX9_IOMUXC1_BASE + SPDIF_SPDIF_I_SELECT_INPUT_OFFSET) +#define USDHC3_IPP_CARD_CLK_IN_SELECT_INPUT (IMX9_IOMUXC1_BASE + USDHC3_IPP_CARD_CLK_IN_SELECT_INPUT_OFFSET) +#define USDHC3_IPP_CMD_IN_SELECT_INPUT (IMX9_IOMUXC1_BASE + USDHC3_IPP_CMD_IN_SELECT_INPUT_OFFSET) +#define USDHC3_IPP_DATO_IN_SELECT_INPUT (IMX9_IOMUXC1_BASE + USDHC3_IPP_DATO_IN_SELECT_INPUT_OFFSET) +#define USDHC3_IPP_DAT1_IN_SELECT_INPUT (IMX9_IOMUXC1_BASE + USDHC3_IPP_DAT1_IN_SELECT_INPUT_OFFSET) +#define USDHC3_IPP_DAT2_IN_SELECT_INPUT (IMX9_IOMUXC1_BASE + USDHC3_IPP_DAT2_IN_SELECT_INPUT_OFFSET) +#define USDHC3_IPP_DAT3_IN_SELECT_INPUT (IMX9_IOMUXC1_BASE + USDHC3_IPP_DAT3_IN_SELECT_INPUT_OFFSET) + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_IOMUX_H */ diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_memorymap.h b/arch/arm64/src/imx9/hardware/imx93/imx93_memorymap.h new file mode 100644 index 0000000000000..050602fc0af0d --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_memorymap.h @@ -0,0 +1,174 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx93/imx93_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_MEMORYMAP_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMX9_GIC_DISTRIBUTOR_BASE (0x48000000UL) +#define IMX9_GIC_REDISTRIBUTOR_BASE (0x48040000UL) +#define IMX9_ANA_OSC_BASE (0x44480000UL) +#define IMX9_AXBS_BASE (0x44510000UL) +#define IMX9_BBNSM_BASE (0x44440000UL) +#define IMX9_BLK_CTRL_BBSMMIX1_BASE (0x44410000UL) +#define IMX9_BLK_CTRL_MLMIX_BASE (0x4A810000UL) +#define IMX9_BLK_CTRL_NIC_WRAPPER1_BASE (0x49000000UL) +#define IMX9_BLK_CTRL_NS_AONMIX1_BASE (0x44210000UL) +#define IMX9_BLK_CTRL_S_AONMIX2_BASE (0x444F0000UL) +#define IMX9_BLK_CTRL_WAKEUPMIX1_BASE (0x42420000UL) +#define IMX9_CAN1_BASE (0x443A0000UL) +#define IMX9_CAN2_BASE (0x425B0000UL) +#define IMX9_CCM_CTRL_BASE (0x44450000UL) +#define IMX9_CM33_MCM_BASE (0x44420000UL) +#define IMX9_DDR_CTRL_BASE (0x4E300000UL) +#define IMX9_BLK_CTRL_DDRMIX_BASE (0x4E010000UL) +#define IMX9_DMA3_BASE (0x44000000UL) +#define IMX9_DMA4_BASE (0x42000000UL) +#define IMX9_PMRO_BASE (0x44484000UL) +#define IMX9_ENET_BASE (0x42890000UL) +#define IMX9_ENET_QOS_BASE (0x428A0000UL) +#define IMX9_FLEXIO1_BASE (0x425C0000UL) +#define IMX9_FLEXIO2_BASE (0x425D0000UL) +#define IMX9_FLEXSPI_BASE (0x425E0000UL) +#define IMX9_FLEXSPI_ARDF_BASE (0x47420000UL) +#define IMX9_FLEXSPI_ATDF_BASE (0x47430000UL) +#define IMX9_GPC_CTRL_CM33_BASE (0x44470000UL) +#define IMX9_GPC_CTRL_CA55_0_BASE (0x44470800UL) +#define IMX9_GPC_CTRL_CA55_1_BASE (0x44471000UL) +#define IMX9_GPC_CTRL_CA55_CLUSTER_BASE (0x44471800UL) +#define IMX9_SAI1_BASE (0x443B0000UL) +#define IMX9_SAI2_BASE (0x42650000UL) +#define IMX9_SAI3_BASE (0x42660000UL) +#define IMX9_I3C1_BASE (0x44330000UL) +#define IMX9_I3C2_BASE (0x42520000UL) +#define IMX9_IOMUXC1_BASE (0x443C0000UL) +#define IMX9_ISI_BASE (0x4AE40000UL) +#define IMX9_LCDIF_BASE (0x4AE30000UL) +#define IMX9_LPI2C1_BASE (0x44340000UL) +#define IMX9_LPI2C2_BASE (0x44350000UL) +#define IMX9_LPI2C3_BASE (0x42530000UL) +#define IMX9_LPI2C4_BASE (0x42540000UL) +#define IMX9_LPI2C5_BASE (0x426B0000UL) +#define IMX9_LPI2C6_BASE (0x426C0000UL) +#define IMX9_LPI2C7_BASE (0x426D0000UL) +#define IMX9_LPI2C8_BASE (0x426E0000UL) +#define IMX9_LPIT1_BASE (0x442F0000UL) +#define IMX9_LPIT2_BASE (0x424C0000UL) +#define IMX9_LPSPI1_BASE (0x44360000UL) +#define IMX9_LPSPI2_BASE (0x44370000UL) +#define IMX9_LPSPI3_BASE (0x42550000UL) +#define IMX9_LPSPI4_BASE (0x42560000UL) +#define IMX9_LPSPI5_BASE (0x426F0000UL) +#define IMX9_LPSPI6_BASE (0x42700000UL) +#define IMX9_LPSPI7_BASE (0x42710000UL) +#define IMX9_LPSPI8_BASE (0x42720000UL) +#define IMX9_LPTMR1_BASE (0x44300000UL) +#define IMX9_LPTMR2_BASE (0x424D0000UL) +#define IMX9_LPUART1_BASE (0x44380000UL) +#define IMX9_LPUART2_BASE (0x44390000UL) +#define IMX9_LPUART3_BASE (0x42570000UL) +#define IMX9_LPUART4_BASE (0x42580000UL) +#define IMX9_LPUART5_BASE (0x42590000UL) +#define IMX9_LPUART6_BASE (0x425A0000UL) +#define IMX9_LPUART7_BASE (0x42690000UL) +#define IMX9_LPUART8_BASE (0x426A0000UL) +#define IMX9_M33_CACHE_MCM_BASE (0x44401000UL) +#define IMX9_BLK_CTRL_MEDIAMIX_BASE (0x4AC10000UL) +#define IMX9_MIPI_CSI_CSR_BASE (0x4AE00000UL) +#define IMX9_MIPI_DSI_BASE (0x4AE10000UL) +#define IMX9_MU1__MUB_BASE (0x44230000UL) +#define IMX9_MU2__MUB_BASE (0x42440000UL) +#define IMX9_NPU_BASE (0x4A900000UL) +#define IMX9_OCOTP_BASE (0x47518000UL) +#define IMX9_OCRAM_MECC1_BASE (0x490A0000UL) +#define IMX9_FLEXSPI_OTFAD1_BASE (0x425E0C00UL) +#define IMX9_PDM_BASE (0x44520000UL) +#define IMX9_ARMPLL_BASE (0x44481000UL) +#define IMX9_AUDIOPLL_BASE (0x44481200UL) +#define IMX9_DRAMPLL_BASE (0x44481300UL) +#define IMX9_SYSPLL_BASE (0x44481100UL) +#define IMX9_VIDEOPLL_BASE (0x44481400UL) +#define IMX9_PXP_BASE (0x4AE20000UL) +#define IMX9_GPIO1_BASE (0x47400000UL) +#define IMX9_GPIO2_BASE (0x43810000UL) +#define IMX9_GPIO3_BASE (0x43820000UL) +#define IMX9_GPIO4_BASE (0x43830000UL) +#define IMX9_ROMCP1_BASE (0x44430000UL) +#define IMX9_ROMCP2_BASE (0x42640000UL) +#define IMX9_ADC1_BASE (0x44530000UL) +#define IMX9_SEMA42_1_BASE (0x44260000UL) +#define IMX9_SEMA42_2_BASE (0x42450000UL) +#define IMX9_SFA_BASE (0x44483000UL) +#define IMX9_SPDIF_BASE (0x42680000UL) +#define IMX9_SRC_SENTINEL_SLICE_BASE (0x44460400UL) +#define IMX9_SRC_AON_SLICE_BASE (0x44460800UL) +#define IMX9_SRC_WKUP_SLICE_BASE (0x44460C00UL) +#define IMX9_SRC_DDR_SLICE_BASE (0x44461000UL) +#define IMX9_SRC_DPHY_SLICE_BASE (0x44461400UL) +#define IMX9_SRC_ML_SLICE_BASE (0x44461800UL) +#define IMX9_SRC_NIC_SLICE_BASE (0x44461C00UL) +#define IMX9_SRC_HSIO_SLICE_BASE (0x44462000UL) +#define IMX9_SRC_MEDIA_SLICE_BASE (0x44462400UL) +#define IMX9_SRC_M33P_SLICE_BASE (0x44462800UL) +#define IMX9_SRC_A55C0_SLICE_BASE (0x44462C00UL) +#define IMX9_SRC_A55C1_SLICE_BASE (0x44463000UL) +#define IMX9_SRC_A55P_SLICE_BASE (0x44463400UL) +#define IMX9_M33_PCF1_BASE (0x443E0000UL) +#define IMX9_M33_PSF1_BASE (0x443F0000UL) +#define IMX9_SYS_CTR_COMPARE_BASE (0x442A0000UL) +#define IMX9_SYS_CTR_CONTROL_BASE (0x44290000UL) +#define IMX9_SYS_CTR_READ_BASE (0x442B0000UL) +#define IMX9_TMU_BASE (0x44482000UL) +#define IMX9_TPM1_BASE (0x44310000UL) +#define IMX9_TPM2_BASE (0x44320000UL) +#define IMX9_TPM3_BASE (0x424E0000UL) +#define IMX9_TPM4_BASE (0x424F0000UL) +#define IMX9_TPM5_BASE (0x42500000UL) +#define IMX9_TPM6_BASE (0x42510000UL) +#define IMX9_TRDC1_BASE (0x44270000UL) +#define IMX9_TRDC2_BASE (0x42460000UL) +#define IMX9_TRGMUX_BASE (0x44531000UL) +#define IMX9_TSTMR1_BASE (0x442C0000UL) +#define IMX9_TSTMR2_BASE (0x42480000UL) +#define IMX9_USB_OTG1_BASE (0x4C100000UL) +#define IMX9_USB_OTG2_BASE (0x4C200000UL) +#define IMX9_USBNC_OTG1_BASE (0x4C100200UL) +#define IMX9_USBNC_OTG2_BASE (0x4C200200UL) +#define IMX9_USDHC1_BASE (0x42850000UL) +#define IMX9_USDHC2_BASE (0x42860000UL) +#define IMX9_USDHC3_BASE (0x428B0000UL) +#define IMX9_WDOG1_BASE (0x442D0000UL) +#define IMX9_WDOG2_BASE (0x442E0000UL) +#define IMX9_WDOG3_BASE (0x42490000UL) +#define IMX9_WDOG4_BASE (0x424A0000UL) +#define IMX9_WDOG5_BASE (0x424B0000UL) +#define IMX9_LPCAC_PC_BASE (0x44400000UL) +#define IMX9_LPCAC_PS_BASE (0x44400800UL) + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_MEMORYMAP_H */ diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_pinmux.h b/arch/arm64/src/imx9/hardware/imx93/imx93_pinmux.h new file mode 100644 index 0000000000000..2a3487d98530a --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_pinmux.h @@ -0,0 +1,634 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx93/imx93_pinmux.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_PINMUX_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_PINMUX_H + +#define IOMUXC_PAD_DAP_TDI_JTAG_MUX_TDI IOMUX_PADCFG(0x443c0000, 0x0, 0x443c03d8, 0x00000000, 0x443c01b0) +#define IOMUXC_PAD_DAP_TDI_MQS2_LEFT IOMUX_PADCFG(0x443c0000, 0x1, 0x00000000, 0x00000000, 0x443c01b0) +#define IOMUXC_PAD_DAP_TDI_CAN2_TX IOMUX_PADCFG(0x443c0000, 0x3, 0x00000000, 0x00000000, 0x443c01b0) +#define IOMUXC_PAD_DAP_TDI_FLEXIO2_FLEXIO30 IOMUX_PADCFG(0x443c0000, 0x4, 0x00000000, 0x00000000, 0x443c01b0) +#define IOMUXC_PAD_DAP_TDI_GPIO3_IO28 IOMUX_PADCFG(0x443c0000, 0x5, 0x00000000, 0x00000000, 0x443c01b0) +#define IOMUXC_PAD_DAP_TDI_LPUART5_RX IOMUX_PADCFG(0x443c0000, 0x6, 0x443c0430, 0x00000000, 0x443c01b0) +#define IOMUXC_PAD_DAP_TMS_SWDIO_JTAG_MUX_TMS IOMUX_PADCFG(0x443c0004, 0x0, 0x443c03dc, 0x00000000, 0x443c01b4) +#define IOMUXC_PAD_DAP_TMS_SWDIO_FLEXIO2_FLEXIO31 IOMUX_PADCFG(0x443c0004, 0x4, 0x00000000, 0x00000000, 0x443c01b4) +#define IOMUXC_PAD_DAP_TMS_SWDIO_GPIO3_IO29 IOMUX_PADCFG(0x443c0004, 0x5, 0x00000000, 0x00000000, 0x443c01b4) +#define IOMUXC_PAD_DAP_TMS_SWDIO_LPUART5_RTS_B IOMUX_PADCFG(0x443c0004, 0x6, 0x00000000, 0x00000000, 0x443c01b4) +#define IOMUXC_PAD_DAP_TCLK_SWCLK_JTAG_MUX_TCK IOMUX_PADCFG(0x443c0008, 0x0, 0x443c03d4, 0x00000000, 0x443c01b8) +#define IOMUXC_PAD_DAP_TCLK_SWCLK_FLEXIO1_FLEXIO30 IOMUX_PADCFG(0x443c0008, 0x4, 0x00000000, 0x00000000, 0x443c01b8) +#define IOMUXC_PAD_DAP_TCLK_SWCLK_GPIO3_IO30 IOMUX_PADCFG(0x443c0008, 0x5, 0x00000000, 0x00000000, 0x443c01b8) +#define IOMUXC_PAD_DAP_TCLK_SWCLK_LPUART5_CTS_B IOMUX_PADCFG(0x443c0008, 0x6, 0x443c042c, 0x00000000, 0x443c01b8) +#define IOMUXC_PAD_DAP_TDO_TRACESWO_JTAG_MUX_TDO IOMUX_PADCFG(0x443c000c, 0x0, 0x00000000, 0x00000000, 0x443c01bc) +#define IOMUXC_PAD_DAP_TDO_TRACESWO_MQS2_RIGHT IOMUX_PADCFG(0x443c000c, 0x1, 0x00000000, 0x00000000, 0x443c01bc) +#define IOMUXC_PAD_DAP_TDO_TRACESWO_CAN2_RX IOMUX_PADCFG(0x443c000c, 0x3, 0x443c0364, 0x00000000, 0x443c01bc) +#define IOMUXC_PAD_DAP_TDO_TRACESWO_FLEXIO1_FLEXIO31 IOMUX_PADCFG(0x443c000c, 0x4, 0x00000000, 0x00000000, 0x443c01bc) +#define IOMUXC_PAD_DAP_TDO_TRACESWO_GPIO3_IO31 IOMUX_PADCFG(0x443c000c, 0x5, 0x00000000, 0x00000000, 0x443c01bc) +#define IOMUXC_PAD_DAP_TDO_TRACESWO_LPUART5_TX IOMUX_PADCFG(0x443c000c, 0x6, 0x443c0434, 0x00000000, 0x443c01bc) +#define IOMUXC_PAD_GPIO_IO00_GPIO2_IO00 IOMUX_PADCFG(0x443c0010, 0x0, 0x00000000, 0x00000000, 0x443c01c0) +#define IOMUXC_PAD_GPIO_IO00_LPI2C3_SDA IOMUX_PADCFG(0x443c0010, 0x1, 0x443c03e4, 0x00000000, 0x443c01c0) +#define IOMUXC_PAD_GPIO_IO00_MEDIAMIX_CAM_CLK IOMUX_PADCFG(0x443c0010, 0x2, 0x00000000, 0x00000000, 0x443c01c0) +#define IOMUXC_PAD_GPIO_IO00_MEDIAMIX_DISP_CLK IOMUX_PADCFG(0x443c0010, 0x3, 0x00000000, 0x00000000, 0x443c01c0) +#define IOMUXC_PAD_GPIO_IO00_LPSPI6_PCS0 IOMUX_PADCFG(0x443c0010, 0x4, 0x00000000, 0x00000000, 0x443c01c0) +#define IOMUXC_PAD_GPIO_IO00_LPUART5_TX IOMUX_PADCFG(0x443c0010, 0x5, 0x443c0434, 0x00000001, 0x443c01c0) +#define IOMUXC_PAD_GPIO_IO00_LPI2C5_SDA IOMUX_PADCFG(0x443c0010, 0x6, 0x443c03ec, 0x00000000, 0x443c01c0) +#define IOMUXC_PAD_GPIO_IO00_FLEXIO1_FLEXIO00 IOMUX_PADCFG(0x443c0010, 0x7, 0x443c036c, 0x00000000, 0x443c01c0) +#define IOMUXC_PAD_GPIO_IO01_GPIO2_IO01 IOMUX_PADCFG(0x443c0014, 0x0, 0x00000000, 0x00000000, 0x443c01c4) +#define IOMUXC_PAD_GPIO_IO01_LPI2C3_SCL IOMUX_PADCFG(0x443c0014, 0x1, 0x443c03e0, 0x00000000, 0x443c01c4) +#define IOMUXC_PAD_GPIO_IO01_MEDIAMIX_CAM_DATA00 IOMUX_PADCFG(0x443c0014, 0x2, 0x00000000, 0x00000000, 0x443c01c4) +#define IOMUXC_PAD_GPIO_IO01_MEDIAMIX_DISP_DE IOMUX_PADCFG(0x443c0014, 0x3, 0x00000000, 0x00000000, 0x443c01c4) +#define IOMUXC_PAD_GPIO_IO01_LPSPI6_SIN IOMUX_PADCFG(0x443c0014, 0x4, 0x00000000, 0x00000000, 0x443c01c4) +#define IOMUXC_PAD_GPIO_IO01_LPUART5_RX IOMUX_PADCFG(0x443c0014, 0x5, 0x443c0430, 0x00000001, 0x443c01c4) +#define IOMUXC_PAD_GPIO_IO01_LPI2C5_SCL IOMUX_PADCFG(0x443c0014, 0x6, 0x443c03e8, 0x00000000, 0x443c01c4) +#define IOMUXC_PAD_GPIO_IO01_FLEXIO1_FLEXIO01 IOMUX_PADCFG(0x443c0014, 0x7, 0x443c0370, 0x00000000, 0x443c01c4) +#define IOMUXC_PAD_GPIO_IO02_GPIO2_IO02 IOMUX_PADCFG(0x443c0018, 0x0, 0x00000000, 0x00000000, 0x443c01c8) +#define IOMUXC_PAD_GPIO_IO02_LPI2C4_SDA IOMUX_PADCFG(0x443c0018, 0x1, 0x00000000, 0x00000000, 0x443c01c8) +#define IOMUXC_PAD_GPIO_IO02_MEDIAMIX_CAM_VSYNC IOMUX_PADCFG(0x443c0018, 0x2, 0x00000000, 0x00000000, 0x443c01c8) +#define IOMUXC_PAD_GPIO_IO02_MEDIAMIX_DISP_VSYNC IOMUX_PADCFG(0x443c0018, 0x3, 0x00000000, 0x00000000, 0x443c01c8) +#define IOMUXC_PAD_GPIO_IO02_LPSPI6_SOUT IOMUX_PADCFG(0x443c0018, 0x4, 0x00000000, 0x00000000, 0x443c01c8) +#define IOMUXC_PAD_GPIO_IO02_LPUART5_CTS_B IOMUX_PADCFG(0x443c0018, 0x5, 0x443c042c, 0x00000001, 0x443c01c8) +#define IOMUXC_PAD_GPIO_IO02_LPI2C6_SDA IOMUX_PADCFG(0x443c0018, 0x6, 0x443c03f4, 0x00000000, 0x443c01c8) +#define IOMUXC_PAD_GPIO_IO02_FLEXIO1_FLEXIO02 IOMUX_PADCFG(0x443c0018, 0x7, 0x443c0374, 0x00000000, 0x443c01c8) +#define IOMUXC_PAD_GPIO_IO03_GPIO2_IO03 IOMUX_PADCFG(0x443c001c, 0x0, 0x00000000, 0x00000000, 0x443c01cc) +#define IOMUXC_PAD_GPIO_IO03_LPI2C4_SCL IOMUX_PADCFG(0x443c001c, 0x1, 0x00000000, 0x00000000, 0x443c01cc) +#define IOMUXC_PAD_GPIO_IO03_MEDIAMIX_CAM_HSYNC IOMUX_PADCFG(0x443c001c, 0x2, 0x00000000, 0x00000000, 0x443c01cc) +#define IOMUXC_PAD_GPIO_IO03_MEDIAMIX_DISP_HSYNC IOMUX_PADCFG(0x443c001c, 0x3, 0x00000000, 0x00000000, 0x443c01cc) +#define IOMUXC_PAD_GPIO_IO03_LPSPI6_SCK IOMUX_PADCFG(0x443c001c, 0x4, 0x00000000, 0x00000000, 0x443c01cc) +#define IOMUXC_PAD_GPIO_IO03_LPUART5_RTS_B IOMUX_PADCFG(0x443c001c, 0x5, 0x00000000, 0x00000000, 0x443c01cc) +#define IOMUXC_PAD_GPIO_IO03_LPI2C6_SCL IOMUX_PADCFG(0x443c001c, 0x6, 0x443c03f0, 0x00000000, 0x443c01cc) +#define IOMUXC_PAD_GPIO_IO03_FLEXIO1_FLEXIO03 IOMUX_PADCFG(0x443c001c, 0x7, 0x443c0378, 0x00000000, 0x443c01cc) +#define IOMUXC_PAD_GPIO_IO04_GPIO2_IO04 IOMUX_PADCFG(0x443c0020, 0x0, 0x00000000, 0x00000000, 0x443c01d0) +#define IOMUXC_PAD_GPIO_IO04_TPM3_CH0 IOMUX_PADCFG(0x443c0020, 0x1, 0x00000000, 0x00000000, 0x443c01d0) +#define IOMUXC_PAD_GPIO_IO04_PDM_CLK IOMUX_PADCFG(0x443c0020, 0x2, 0x00000000, 0x00000000, 0x443c01d0) +#define IOMUXC_PAD_GPIO_IO04_MEDIAMIX_DISP_DATA00 IOMUX_PADCFG(0x443c0020, 0x3, 0x00000000, 0x00000000, 0x443c01d0) +#define IOMUXC_PAD_GPIO_IO04_LPSPI7_PCS0 IOMUX_PADCFG(0x443c0020, 0x4, 0x00000000, 0x00000000, 0x443c01d0) +#define IOMUXC_PAD_GPIO_IO04_LPUART6_TX IOMUX_PADCFG(0x443c0020, 0x5, 0x00000000, 0x00000000, 0x443c01d0) +#define IOMUXC_PAD_GPIO_IO04_LPI2C6_SDA IOMUX_PADCFG(0x443c0020, 0x6, 0x443c03f4, 0x00000001, 0x443c01d0) +#define IOMUXC_PAD_GPIO_IO04_FLEXIO1_FLEXIO04 IOMUX_PADCFG(0x443c0020, 0x7, 0x443c037c, 0x00000000, 0x443c01d0) +#define IOMUXC_PAD_GPIO_IO05_GPIO2_IO05 IOMUX_PADCFG(0x443c0024, 0x0, 0x00000000, 0x00000000, 0x443c01d4) +#define IOMUXC_PAD_GPIO_IO05_TPM4_CH0 IOMUX_PADCFG(0x443c0024, 0x1, 0x00000000, 0x00000000, 0x443c01d4) +#define IOMUXC_PAD_GPIO_IO05_PDM_BIT_STREAM00 IOMUX_PADCFG(0x443c0024, 0x2, 0x443c0438, 0x00000000, 0x443c01d4) +#define IOMUXC_PAD_GPIO_IO05_MEDIAMIX_DISP_DATA01 IOMUX_PADCFG(0x443c0024, 0x3, 0x00000000, 0x00000000, 0x443c01d4) +#define IOMUXC_PAD_GPIO_IO05_LPSPI7_SIN IOMUX_PADCFG(0x443c0024, 0x4, 0x00000000, 0x00000000, 0x443c01d4) +#define IOMUXC_PAD_GPIO_IO05_LPUART6_RX IOMUX_PADCFG(0x443c0024, 0x5, 0x00000000, 0x00000000, 0x443c01d4) +#define IOMUXC_PAD_GPIO_IO05_LPI2C6_SCL IOMUX_PADCFG(0x443c0024, 0x6, 0x443c03f0, 0x00000001, 0x443c01d4) +#define IOMUXC_PAD_GPIO_IO05_FLEXIO1_FLEXIO05 IOMUX_PADCFG(0x443c0024, 0x7, 0x443c0380, 0x00000000, 0x443c01d4) +#define IOMUXC_PAD_GPIO_IO06_GPIO2_IO06 IOMUX_PADCFG(0x443c0028, 0x0, 0x00000000, 0x00000000, 0x443c01d8) +#define IOMUXC_PAD_GPIO_IO06_TPM5_CH0 IOMUX_PADCFG(0x443c0028, 0x1, 0x00000000, 0x00000000, 0x443c01d8) +#define IOMUXC_PAD_GPIO_IO06_PDM_BIT_STREAM01 IOMUX_PADCFG(0x443c0028, 0x2, 0x443c043c, 0x00000000, 0x443c01d8) +#define IOMUXC_PAD_GPIO_IO06_MEDIAMIX_DISP_DATA02 IOMUX_PADCFG(0x443c0028, 0x3, 0x00000000, 0x00000000, 0x443c01d8) +#define IOMUXC_PAD_GPIO_IO06_LPSPI7_SOUT IOMUX_PADCFG(0x443c0028, 0x4, 0x00000000, 0x00000000, 0x443c01d8) +#define IOMUXC_PAD_GPIO_IO06_LPUART6_CTS_B IOMUX_PADCFG(0x443c0028, 0x5, 0x00000000, 0x00000000, 0x443c01d8) +#define IOMUXC_PAD_GPIO_IO06_LPI2C7_SDA IOMUX_PADCFG(0x443c0028, 0x6, 0x443c03fc, 0x00000000, 0x443c01d8) +#define IOMUXC_PAD_GPIO_IO06_FLEXIO1_FLEXIO06 IOMUX_PADCFG(0x443c0028, 0x7, 0x443c0384, 0x00000000, 0x443c01d8) +#define IOMUXC_PAD_GPIO_IO07_GPIO2_IO07 IOMUX_PADCFG(0x443c002c, 0x0, 0x00000000, 0x00000000, 0x443c01dc) +#define IOMUXC_PAD_GPIO_IO07_LPSPI3_PCS1 IOMUX_PADCFG(0x443c002c, 0x1, 0x00000000, 0x00000000, 0x443c01dc) +#define IOMUXC_PAD_GPIO_IO07_MEDIAMIX_CAM_DATA01 IOMUX_PADCFG(0x443c002c, 0x2, 0x00000000, 0x00000000, 0x443c01dc) +#define IOMUXC_PAD_GPIO_IO07_MEDIAMIX_DISP_DATA03 IOMUX_PADCFG(0x443c002c, 0x3, 0x00000000, 0x00000000, 0x443c01dc) +#define IOMUXC_PAD_GPIO_IO07_LPSPI7_SCK IOMUX_PADCFG(0x443c002c, 0x4, 0x00000000, 0x00000000, 0x443c01dc) +#define IOMUXC_PAD_GPIO_IO07_LPUART6_RTS_B IOMUX_PADCFG(0x443c002c, 0x5, 0x00000000, 0x00000000, 0x443c01dc) +#define IOMUXC_PAD_GPIO_IO07_LPI2C7_SCL IOMUX_PADCFG(0x443c002c, 0x6, 0x443c03f8, 0x00000000, 0x443c01dc) +#define IOMUXC_PAD_GPIO_IO07_FLEXIO1_FLEXIO07 IOMUX_PADCFG(0x443c002c, 0x7, 0x443c0388, 0x00000000, 0x443c01dc) +#define IOMUXC_PAD_GPIO_IO08_GPIO2_IO08 IOMUX_PADCFG(0x443c0030, 0x0, 0x00000000, 0x00000000, 0x443c01e0) +#define IOMUXC_PAD_GPIO_IO08_LPSPI3_PCS0 IOMUX_PADCFG(0x443c0030, 0x1, 0x00000000, 0x00000000, 0x443c01e0) +#define IOMUXC_PAD_GPIO_IO08_MEDIAMIX_CAM_DATA02 IOMUX_PADCFG(0x443c0030, 0x2, 0x00000000, 0x00000000, 0x443c01e0) +#define IOMUXC_PAD_GPIO_IO08_MEDIAMIX_DISP_DATA04 IOMUX_PADCFG(0x443c0030, 0x3, 0x00000000, 0x00000000, 0x443c01e0) +#define IOMUXC_PAD_GPIO_IO08_TPM6_CH0 IOMUX_PADCFG(0x443c0030, 0x4, 0x00000000, 0x00000000, 0x443c01e0) +#define IOMUXC_PAD_GPIO_IO08_LPUART7_TX IOMUX_PADCFG(0x443c0030, 0x5, 0x00000000, 0x00000000, 0x443c01e0) +#define IOMUXC_PAD_GPIO_IO08_LPI2C7_SDA IOMUX_PADCFG(0x443c0030, 0x6, 0x443c03fc, 0x00000001, 0x443c01e0) +#define IOMUXC_PAD_GPIO_IO08_FLEXIO1_FLEXIO08 IOMUX_PADCFG(0x443c0030, 0x7, 0x443c038c, 0x00000000, 0x443c01e0) +#define IOMUXC_PAD_GPIO_IO09_GPIO2_IO09 IOMUX_PADCFG(0x443c0034, 0x0, 0x00000000, 0x00000000, 0x443c01e4) +#define IOMUXC_PAD_GPIO_IO09_LPSPI3_SIN IOMUX_PADCFG(0x443c0034, 0x1, 0x00000000, 0x00000000, 0x443c01e4) +#define IOMUXC_PAD_GPIO_IO09_MEDIAMIX_CAM_DATA03 IOMUX_PADCFG(0x443c0034, 0x2, 0x00000000, 0x00000000, 0x443c01e4) +#define IOMUXC_PAD_GPIO_IO09_MEDIAMIX_DISP_DATA05 IOMUX_PADCFG(0x443c0034, 0x3, 0x00000000, 0x00000000, 0x443c01e4) +#define IOMUXC_PAD_GPIO_IO09_TPM3_EXTCLK IOMUX_PADCFG(0x443c0034, 0x4, 0x00000000, 0x00000000, 0x443c01e4) +#define IOMUXC_PAD_GPIO_IO09_LPUART7_RX IOMUX_PADCFG(0x443c0034, 0x5, 0x00000000, 0x00000000, 0x443c01e4) +#define IOMUXC_PAD_GPIO_IO09_LPI2C7_SCL IOMUX_PADCFG(0x443c0034, 0x6, 0x443c03f8, 0x00000001, 0x443c01e4) +#define IOMUXC_PAD_GPIO_IO09_FLEXIO1_FLEXIO09 IOMUX_PADCFG(0x443c0034, 0x7, 0x443c0390, 0x00000000, 0x443c01e4) +#define IOMUXC_PAD_GPIO_IO10_GPIO2_IO10 IOMUX_PADCFG(0x443c0038, 0x0, 0x00000000, 0x00000000, 0x443c01e8) +#define IOMUXC_PAD_GPIO_IO10_LPSPI3_SOUT IOMUX_PADCFG(0x443c0038, 0x1, 0x00000000, 0x00000000, 0x443c01e8) +#define IOMUXC_PAD_GPIO_IO10_MEDIAMIX_CAM_DATA04 IOMUX_PADCFG(0x443c0038, 0x2, 0x00000000, 0x00000000, 0x443c01e8) +#define IOMUXC_PAD_GPIO_IO10_MEDIAMIX_DISP_DATA06 IOMUX_PADCFG(0x443c0038, 0x3, 0x00000000, 0x00000000, 0x443c01e8) +#define IOMUXC_PAD_GPIO_IO10_TPM4_EXTCLK IOMUX_PADCFG(0x443c0038, 0x4, 0x00000000, 0x00000000, 0x443c01e8) +#define IOMUXC_PAD_GPIO_IO10_LPUART7_CTS_B IOMUX_PADCFG(0x443c0038, 0x5, 0x00000000, 0x00000000, 0x443c01e8) +#define IOMUXC_PAD_GPIO_IO10_LPI2C8_SDA IOMUX_PADCFG(0x443c0038, 0x6, 0x443c0404, 0x00000000, 0x443c01e8) +#define IOMUXC_PAD_GPIO_IO10_FLEXIO1_FLEXIO10 IOMUX_PADCFG(0x443c0038, 0x7, 0x443c0394, 0x00000000, 0x443c01e8) +#define IOMUXC_PAD_GPIO_IO11_GPIO2_IO11 IOMUX_PADCFG(0x443c003c, 0x0, 0x00000000, 0x00000000, 0x443c01ec) +#define IOMUXC_PAD_GPIO_IO11_LPSPI3_SCK IOMUX_PADCFG(0x443c003c, 0x1, 0x00000000, 0x00000000, 0x443c01ec) +#define IOMUXC_PAD_GPIO_IO11_MEDIAMIX_CAM_DATA05 IOMUX_PADCFG(0x443c003c, 0x2, 0x00000000, 0x00000000, 0x443c01ec) +#define IOMUXC_PAD_GPIO_IO11_MEDIAMIX_DISP_DATA07 IOMUX_PADCFG(0x443c003c, 0x3, 0x00000000, 0x00000000, 0x443c01ec) +#define IOMUXC_PAD_GPIO_IO11_TPM5_EXTCLK IOMUX_PADCFG(0x443c003c, 0x4, 0x00000000, 0x00000000, 0x443c01ec) +#define IOMUXC_PAD_GPIO_IO11_LPUART7_RTS_B IOMUX_PADCFG(0x443c003c, 0x5, 0x00000000, 0x00000000, 0x443c01ec) +#define IOMUXC_PAD_GPIO_IO11_LPI2C8_SCL IOMUX_PADCFG(0x443c003c, 0x6, 0x443c0400, 0x00000000, 0x443c01ec) +#define IOMUXC_PAD_GPIO_IO11_FLEXIO1_FLEXIO11 IOMUX_PADCFG(0x443c003c, 0x7, 0x443c0398, 0x00000000, 0x443c01ec) +#define IOMUXC_PAD_GPIO_IO12_GPIO2_IO12 IOMUX_PADCFG(0x443c0040, 0x0, 0x00000000, 0x00000000, 0x443c01f0) +#define IOMUXC_PAD_GPIO_IO12_TPM3_CH2 IOMUX_PADCFG(0x443c0040, 0x1, 0x00000000, 0x00000000, 0x443c01f0) +#define IOMUXC_PAD_GPIO_IO12_PDM_BIT_STREAM02 IOMUX_PADCFG(0x443c0040, 0x2, 0x443c0440, 0x00000000, 0x443c01f0) +#define IOMUXC_PAD_GPIO_IO12_MEDIAMIX_DISP_DATA08 IOMUX_PADCFG(0x443c0040, 0x3, 0x00000000, 0x00000000, 0x443c01f0) +#define IOMUXC_PAD_GPIO_IO12_LPSPI8_PCS0 IOMUX_PADCFG(0x443c0040, 0x4, 0x00000000, 0x00000000, 0x443c01f0) +#define IOMUXC_PAD_GPIO_IO12_LPUART8_TX IOMUX_PADCFG(0x443c0040, 0x5, 0x00000000, 0x00000000, 0x443c01f0) +#define IOMUXC_PAD_GPIO_IO12_LPI2C8_SDA IOMUX_PADCFG(0x443c0040, 0x6, 0x443c0404, 0x00000001, 0x443c01f0) +#define IOMUXC_PAD_GPIO_IO12_SAI3_RX_SYNC IOMUX_PADCFG(0x443c0040, 0x7, 0x443c0450, 0x00000000, 0x443c01f0) +#define IOMUXC_PAD_GPIO_IO13_GPIO2_IO13 IOMUX_PADCFG(0x443c0044, 0x0, 0x00000000, 0x00000000, 0x443c01f4) +#define IOMUXC_PAD_GPIO_IO13_TPM4_CH2 IOMUX_PADCFG(0x443c0044, 0x1, 0x00000000, 0x00000000, 0x443c01f4) +#define IOMUXC_PAD_GPIO_IO13_PDM_BIT_STREAM03 IOMUX_PADCFG(0x443c0044, 0x2, 0x443c0444, 0x00000000, 0x443c01f4) +#define IOMUXC_PAD_GPIO_IO13_MEDIAMIX_DISP_DATA09 IOMUX_PADCFG(0x443c0044, 0x3, 0x00000000, 0x00000000, 0x443c01f4) +#define IOMUXC_PAD_GPIO_IO13_LPSPI8_SIN IOMUX_PADCFG(0x443c0044, 0x4, 0x00000000, 0x00000000, 0x443c01f4) +#define IOMUXC_PAD_GPIO_IO13_LPUART8_RX IOMUX_PADCFG(0x443c0044, 0x5, 0x00000000, 0x00000000, 0x443c01f4) +#define IOMUXC_PAD_GPIO_IO13_LPI2C8_SCL IOMUX_PADCFG(0x443c0044, 0x6, 0x443c0400, 0x00000001, 0x443c01f4) +#define IOMUXC_PAD_GPIO_IO13_FLEXIO1_FLEXIO13 IOMUX_PADCFG(0x443c0044, 0x7, 0x443c039c, 0x00000000, 0x443c01f4) +#define IOMUXC_PAD_GPIO_IO14_GPIO2_IO14 IOMUX_PADCFG(0x443c0048, 0x0, 0x00000000, 0x00000000, 0x443c01f8) +#define IOMUXC_PAD_GPIO_IO14_LPUART3_TX IOMUX_PADCFG(0x443c0048, 0x1, 0x443c041c, 0x00000000, 0x443c01f8) +#define IOMUXC_PAD_GPIO_IO14_MEDIAMIX_CAM_DATA06 IOMUX_PADCFG(0x443c0048, 0x2, 0x00000000, 0x00000000, 0x443c01f8) +#define IOMUXC_PAD_GPIO_IO14_MEDIAMIX_DISP_DATA10 IOMUX_PADCFG(0x443c0048, 0x3, 0x00000000, 0x00000000, 0x443c01f8) +#define IOMUXC_PAD_GPIO_IO14_LPSPI8_SOUT IOMUX_PADCFG(0x443c0048, 0x4, 0x00000000, 0x00000000, 0x443c01f8) +#define IOMUXC_PAD_GPIO_IO14_LPUART8_CTS_B IOMUX_PADCFG(0x443c0048, 0x5, 0x00000000, 0x00000000, 0x443c01f8) +#define IOMUXC_PAD_GPIO_IO14_LPUART4_TX IOMUX_PADCFG(0x443c0048, 0x6, 0x443c0428, 0x00000000, 0x443c01f8) +#define IOMUXC_PAD_GPIO_IO14_FLEXIO1_FLEXIO14 IOMUX_PADCFG(0x443c0048, 0x7, 0x443c03a0, 0x00000000, 0x443c01f8) +#define IOMUXC_PAD_GPIO_IO15_GPIO2_IO15 IOMUX_PADCFG(0x443c004c, 0x0, 0x00000000, 0x00000000, 0x443c01fc) +#define IOMUXC_PAD_GPIO_IO15_LPUART3_RX IOMUX_PADCFG(0x443c004c, 0x1, 0x443c0418, 0x00000000, 0x443c01fc) +#define IOMUXC_PAD_GPIO_IO15_MEDIAMIX_CAM_DATA07 IOMUX_PADCFG(0x443c004c, 0x2, 0x00000000, 0x00000000, 0x443c01fc) +#define IOMUXC_PAD_GPIO_IO15_MEDIAMIX_DISP_DATA11 IOMUX_PADCFG(0x443c004c, 0x3, 0x00000000, 0x00000000, 0x443c01fc) +#define IOMUXC_PAD_GPIO_IO15_LPSPI8_SCK IOMUX_PADCFG(0x443c004c, 0x4, 0x00000000, 0x00000000, 0x443c01fc) +#define IOMUXC_PAD_GPIO_IO15_LPUART8_RTS_B IOMUX_PADCFG(0x443c004c, 0x5, 0x00000000, 0x00000000, 0x443c01fc) +#define IOMUXC_PAD_GPIO_IO15_LPUART4_RX IOMUX_PADCFG(0x443c004c, 0x6, 0x443c0424, 0x00000000, 0x443c01fc) +#define IOMUXC_PAD_GPIO_IO15_FLEXIO1_FLEXIO15 IOMUX_PADCFG(0x443c004c, 0x7, 0x443c03a4, 0x00000000, 0x443c01fc) +#define IOMUXC_PAD_GPIO_IO16_GPIO2_IO16 IOMUX_PADCFG(0x443c0050, 0x0, 0x00000000, 0x00000000, 0x443c0200) +#define IOMUXC_PAD_GPIO_IO16_SAI3_TX_BCLK IOMUX_PADCFG(0x443c0050, 0x1, 0x00000000, 0x00000000, 0x443c0200) +#define IOMUXC_PAD_GPIO_IO16_PDM_BIT_STREAM02 IOMUX_PADCFG(0x443c0050, 0x2, 0x443c0440, 0x00000001, 0x443c0200) +#define IOMUXC_PAD_GPIO_IO16_MEDIAMIX_DISP_DATA12 IOMUX_PADCFG(0x443c0050, 0x3, 0x00000000, 0x00000000, 0x443c0200) +#define IOMUXC_PAD_GPIO_IO16_LPUART3_CTS_B IOMUX_PADCFG(0x443c0050, 0x4, 0x443c0414, 0x00000000, 0x443c0200) +#define IOMUXC_PAD_GPIO_IO16_LPSPI4_PCS2 IOMUX_PADCFG(0x443c0050, 0x5, 0x00000000, 0x00000000, 0x443c0200) +#define IOMUXC_PAD_GPIO_IO16_LPUART4_CTS_B IOMUX_PADCFG(0x443c0050, 0x6, 0x443c0420, 0x00000000, 0x443c0200) +#define IOMUXC_PAD_GPIO_IO16_FLEXIO1_FLEXIO16 IOMUX_PADCFG(0x443c0050, 0x7, 0x443c03a8, 0x00000000, 0x443c0200) +#define IOMUXC_PAD_GPIO_IO17_GPIO2_IO17 IOMUX_PADCFG(0x443c0054, 0x0, 0x00000000, 0x00000000, 0x443c0204) +#define IOMUXC_PAD_GPIO_IO17_SAI3_MCLK IOMUX_PADCFG(0x443c0054, 0x1, 0x00000000, 0x00000000, 0x443c0204) +#define IOMUXC_PAD_GPIO_IO17_MEDIAMIX_CAM_DATA08 IOMUX_PADCFG(0x443c0054, 0x2, 0x00000000, 0x00000000, 0x443c0204) +#define IOMUXC_PAD_GPIO_IO17_MEDIAMIX_DISP_DATA13 IOMUX_PADCFG(0x443c0054, 0x3, 0x00000000, 0x00000000, 0x443c0204) +#define IOMUXC_PAD_GPIO_IO17_LPUART3_RTS_B IOMUX_PADCFG(0x443c0054, 0x4, 0x00000000, 0x00000000, 0x443c0204) +#define IOMUXC_PAD_GPIO_IO17_LPSPI4_PCS1 IOMUX_PADCFG(0x443c0054, 0x5, 0x00000000, 0x00000000, 0x443c0204) +#define IOMUXC_PAD_GPIO_IO17_LPUART4_RTS_B IOMUX_PADCFG(0x443c0054, 0x6, 0x00000000, 0x00000000, 0x443c0204) +#define IOMUXC_PAD_GPIO_IO17_FLEXIO1_FLEXIO17 IOMUX_PADCFG(0x443c0054, 0x7, 0x443c03ac, 0x00000000, 0x443c0204) +#define IOMUXC_PAD_GPIO_IO18_GPIO2_IO18 IOMUX_PADCFG(0x443c0058, 0x0, 0x00000000, 0x00000000, 0x443c0208) +#define IOMUXC_PAD_GPIO_IO18_SAI3_RX_BCLK IOMUX_PADCFG(0x443c0058, 0x1, 0x443c044c, 0x00000000, 0x443c0208) +#define IOMUXC_PAD_GPIO_IO18_MEDIAMIX_CAM_DATA09 IOMUX_PADCFG(0x443c0058, 0x2, 0x00000000, 0x00000000, 0x443c0208) +#define IOMUXC_PAD_GPIO_IO18_MEDIAMIX_DISP_DATA14 IOMUX_PADCFG(0x443c0058, 0x3, 0x00000000, 0x00000000, 0x443c0208) +#define IOMUXC_PAD_GPIO_IO18_LPSPI5_PCS0 IOMUX_PADCFG(0x443c0058, 0x4, 0x00000000, 0x00000000, 0x443c0208) +#define IOMUXC_PAD_GPIO_IO18_LPSPI4_PCS0 IOMUX_PADCFG(0x443c0058, 0x5, 0x00000000, 0x00000000, 0x443c0208) +#define IOMUXC_PAD_GPIO_IO18_TPM5_CH2 IOMUX_PADCFG(0x443c0058, 0x6, 0x00000000, 0x00000000, 0x443c0208) +#define IOMUXC_PAD_GPIO_IO18_FLEXIO1_FLEXIO18 IOMUX_PADCFG(0x443c0058, 0x7, 0x443c03b0, 0x00000000, 0x443c0208) +#define IOMUXC_PAD_GPIO_IO19_GPIO2_IO19 IOMUX_PADCFG(0x443c005c, 0x0, 0x00000000, 0x00000000, 0x443c020c) +#define IOMUXC_PAD_GPIO_IO19_SAI3_RX_SYNC IOMUX_PADCFG(0x443c005c, 0x1, 0x443c0450, 0x00000001, 0x443c020c) +#define IOMUXC_PAD_GPIO_IO19_PDM_BIT_STREAM03 IOMUX_PADCFG(0x443c005c, 0x2, 0x443c0444, 0x00000001, 0x443c020c) +#define IOMUXC_PAD_GPIO_IO19_MEDIAMIX_DISP_DATA15 IOMUX_PADCFG(0x443c005c, 0x3, 0x00000000, 0x00000000, 0x443c020c) +#define IOMUXC_PAD_GPIO_IO19_LPSPI5_SIN IOMUX_PADCFG(0x443c005c, 0x4, 0x00000000, 0x00000000, 0x443c020c) +#define IOMUXC_PAD_GPIO_IO19_LPSPI4_SIN IOMUX_PADCFG(0x443c005c, 0x5, 0x00000000, 0x00000000, 0x443c020c) +#define IOMUXC_PAD_GPIO_IO19_TPM6_CH2 IOMUX_PADCFG(0x443c005c, 0x6, 0x00000000, 0x00000000, 0x443c020c) +#define IOMUXC_PAD_GPIO_IO19_SAI3_TX_DATA00 IOMUX_PADCFG(0x443c005c, 0x7, 0x00000000, 0x00000000, 0x443c020c) +#define IOMUXC_PAD_GPIO_IO20_GPIO2_IO20 IOMUX_PADCFG(0x443c0060, 0x0, 0x00000000, 0x00000000, 0x443c0210) +#define IOMUXC_PAD_GPIO_IO20_SAI3_RX_DATA00 IOMUX_PADCFG(0x443c0060, 0x1, 0x00000000, 0x00000000, 0x443c0210) +#define IOMUXC_PAD_GPIO_IO20_PDM_BIT_STREAM00 IOMUX_PADCFG(0x443c0060, 0x2, 0x443c0438, 0x00000001, 0x443c0210) +#define IOMUXC_PAD_GPIO_IO20_MEDIAMIX_DISP_DATA16 IOMUX_PADCFG(0x443c0060, 0x3, 0x00000000, 0x00000000, 0x443c0210) +#define IOMUXC_PAD_GPIO_IO20_LPSPI5_SOUT IOMUX_PADCFG(0x443c0060, 0x4, 0x00000000, 0x00000000, 0x443c0210) +#define IOMUXC_PAD_GPIO_IO20_LPSPI4_SOUT IOMUX_PADCFG(0x443c0060, 0x5, 0x00000000, 0x00000000, 0x443c0210) +#define IOMUXC_PAD_GPIO_IO20_TPM3_CH1 IOMUX_PADCFG(0x443c0060, 0x6, 0x00000000, 0x00000000, 0x443c0210) +#define IOMUXC_PAD_GPIO_IO20_FLEXIO1_FLEXIO20 IOMUX_PADCFG(0x443c0060, 0x7, 0x443c03b4, 0x00000000, 0x443c0210) +#define IOMUXC_PAD_GPIO_IO21_GPIO2_IO21 IOMUX_PADCFG(0x443c0064, 0x0, 0x00000000, 0x00000000, 0x443c0214) +#define IOMUXC_PAD_GPIO_IO21_SAI3_TX_DATA00 IOMUX_PADCFG(0x443c0064, 0x1, 0x00000000, 0x00000000, 0x443c0214) +#define IOMUXC_PAD_GPIO_IO21_PDM_CLK IOMUX_PADCFG(0x443c0064, 0x2, 0x00000000, 0x00000000, 0x443c0214) +#define IOMUXC_PAD_GPIO_IO21_MEDIAMIX_DISP_DATA17 IOMUX_PADCFG(0x443c0064, 0x3, 0x00000000, 0x00000000, 0x443c0214) +#define IOMUXC_PAD_GPIO_IO21_LPSPI5_SCK IOMUX_PADCFG(0x443c0064, 0x4, 0x00000000, 0x00000000, 0x443c0214) +#define IOMUXC_PAD_GPIO_IO21_LPSPI4_SCK IOMUX_PADCFG(0x443c0064, 0x5, 0x00000000, 0x00000000, 0x443c0214) +#define IOMUXC_PAD_GPIO_IO21_TPM4_CH1 IOMUX_PADCFG(0x443c0064, 0x6, 0x00000000, 0x00000000, 0x443c0214) +#define IOMUXC_PAD_GPIO_IO21_SAI3_RX_BCLK IOMUX_PADCFG(0x443c0064, 0x7, 0x443c044c, 0x00000001, 0x443c0214) +#define IOMUXC_PAD_GPIO_IO22_GPIO2_IO22 IOMUX_PADCFG(0x443c0068, 0x0, 0x00000000, 0x00000000, 0x443c0218) +#define IOMUXC_PAD_GPIO_IO22_USDHC3_CLK IOMUX_PADCFG(0x443c0068, 0x1, 0x443c0458, 0x00000000, 0x443c0218) +#define IOMUXC_PAD_GPIO_IO22_SPDIF_IN IOMUX_PADCFG(0x443c0068, 0x2, 0x443c0454, 0x00000000, 0x443c0218) +#define IOMUXC_PAD_GPIO_IO22_MEDIAMIX_DISP_DATA18 IOMUX_PADCFG(0x443c0068, 0x3, 0x00000000, 0x00000000, 0x443c0218) +#define IOMUXC_PAD_GPIO_IO22_TPM5_CH1 IOMUX_PADCFG(0x443c0068, 0x4, 0x00000000, 0x00000000, 0x443c0218) +#define IOMUXC_PAD_GPIO_IO22_TPM6_EXTCLK IOMUX_PADCFG(0x443c0068, 0x5, 0x00000000, 0x00000000, 0x443c0218) +#define IOMUXC_PAD_GPIO_IO22_LPI2C5_SDA IOMUX_PADCFG(0x443c0068, 0x6, 0x443c03ec, 0x00000001, 0x443c0218) +#define IOMUXC_PAD_GPIO_IO22_FLEXIO1_FLEXIO22 IOMUX_PADCFG(0x443c0068, 0x7, 0x443c03b8, 0x00000000, 0x443c0218) +#define IOMUXC_PAD_GPIO_IO23_GPIO2_IO23 IOMUX_PADCFG(0x443c006c, 0x0, 0x00000000, 0x00000000, 0x443c021c) +#define IOMUXC_PAD_GPIO_IO23_USDHC3_CMD IOMUX_PADCFG(0x443c006c, 0x1, 0x443c045c, 0x00000000, 0x443c021c) +#define IOMUXC_PAD_GPIO_IO23_SPDIF_OUT IOMUX_PADCFG(0x443c006c, 0x2, 0x00000000, 0x00000000, 0x443c021c) +#define IOMUXC_PAD_GPIO_IO23_MEDIAMIX_DISP_DATA19 IOMUX_PADCFG(0x443c006c, 0x3, 0x00000000, 0x00000000, 0x443c021c) +#define IOMUXC_PAD_GPIO_IO23_TPM6_CH1 IOMUX_PADCFG(0x443c006c, 0x4, 0x00000000, 0x00000000, 0x443c021c) +#define IOMUXC_PAD_GPIO_IO23_LPI2C5_SCL IOMUX_PADCFG(0x443c006c, 0x6, 0x443c03e8, 0x00000001, 0x443c021c) +#define IOMUXC_PAD_GPIO_IO23_FLEXIO1_FLEXIO23 IOMUX_PADCFG(0x443c006c, 0x7, 0x443c03bc, 0x00000000, 0x443c021c) +#define IOMUXC_PAD_GPIO_IO24_GPIO2_IO24 IOMUX_PADCFG(0x443c0070, 0x0, 0x00000000, 0x00000000, 0x443c0220) +#define IOMUXC_PAD_GPIO_IO24_USDHC3_DATA0 IOMUX_PADCFG(0x443c0070, 0x1, 0x443c0460, 0x00000000, 0x443c0220) +#define IOMUXC_PAD_GPIO_IO24_MEDIAMIX_DISP_DATA20 IOMUX_PADCFG(0x443c0070, 0x3, 0x00000000, 0x00000000, 0x443c0220) +#define IOMUXC_PAD_GPIO_IO24_TPM3_CH3 IOMUX_PADCFG(0x443c0070, 0x4, 0x00000000, 0x00000000, 0x443c0220) +#define IOMUXC_PAD_GPIO_IO24_JTAG_MUX_TDO IOMUX_PADCFG(0x443c0070, 0x5, 0x00000000, 0x00000000, 0x443c0220) +#define IOMUXC_PAD_GPIO_IO24_LPSPI6_PCS1 IOMUX_PADCFG(0x443c0070, 0x6, 0x00000000, 0x00000000, 0x443c0220) +#define IOMUXC_PAD_GPIO_IO24_FLEXIO1_FLEXIO24 IOMUX_PADCFG(0x443c0070, 0x7, 0x443c03c0, 0x00000000, 0x443c0220) +#define IOMUXC_PAD_GPIO_IO25_GPIO2_IO25 IOMUX_PADCFG(0x443c0074, 0x0, 0x00000000, 0x00000000, 0x443c0224) +#define IOMUXC_PAD_GPIO_IO25_USDHC3_DATA1 IOMUX_PADCFG(0x443c0074, 0x1, 0x443c0464, 0x00000000, 0x443c0224) +#define IOMUXC_PAD_GPIO_IO25_CAN2_TX IOMUX_PADCFG(0x443c0074, 0x2, 0x00000000, 0x00000000, 0x443c0224) +#define IOMUXC_PAD_GPIO_IO25_MEDIAMIX_DISP_DATA21 IOMUX_PADCFG(0x443c0074, 0x3, 0x00000000, 0x00000000, 0x443c0224) +#define IOMUXC_PAD_GPIO_IO25_TPM4_CH3 IOMUX_PADCFG(0x443c0074, 0x4, 0x00000000, 0x00000000, 0x443c0224) +#define IOMUXC_PAD_GPIO_IO25_JTAG_MUX_TCK IOMUX_PADCFG(0x443c0074, 0x5, 0x443c03d4, 0x00000001, 0x443c0224) +#define IOMUXC_PAD_GPIO_IO25_LPSPI7_PCS1 IOMUX_PADCFG(0x443c0074, 0x6, 0x00000000, 0x00000000, 0x443c0224) +#define IOMUXC_PAD_GPIO_IO25_FLEXIO1_FLEXIO25 IOMUX_PADCFG(0x443c0074, 0x7, 0x443c03c4, 0x00000000, 0x443c0224) +#define IOMUXC_PAD_GPIO_IO26_GPIO2_IO26 IOMUX_PADCFG(0x443c0078, 0x0, 0x00000000, 0x00000000, 0x443c0228) +#define IOMUXC_PAD_GPIO_IO26_USDHC3_DATA2 IOMUX_PADCFG(0x443c0078, 0x1, 0x443c0468, 0x00000000, 0x443c0228) +#define IOMUXC_PAD_GPIO_IO26_PDM_BIT_STREAM01 IOMUX_PADCFG(0x443c0078, 0x2, 0x443c043c, 0x00000001, 0x443c0228) +#define IOMUXC_PAD_GPIO_IO26_MEDIAMIX_DISP_DATA22 IOMUX_PADCFG(0x443c0078, 0x3, 0x00000000, 0x00000000, 0x443c0228) +#define IOMUXC_PAD_GPIO_IO26_TPM5_CH3 IOMUX_PADCFG(0x443c0078, 0x4, 0x00000000, 0x00000000, 0x443c0228) +#define IOMUXC_PAD_GPIO_IO26_JTAG_MUX_TDI IOMUX_PADCFG(0x443c0078, 0x5, 0x443c03d8, 0x00000001, 0x443c0228) +#define IOMUXC_PAD_GPIO_IO26_LPSPI8_PCS1 IOMUX_PADCFG(0x443c0078, 0x6, 0x00000000, 0x00000000, 0x443c0228) +#define IOMUXC_PAD_GPIO_IO26_SAI3_TX_SYNC IOMUX_PADCFG(0x443c0078, 0x7, 0x00000000, 0x00000000, 0x443c0228) +#define IOMUXC_PAD_GPIO_IO27_GPIO2_IO27 IOMUX_PADCFG(0x443c007c, 0x0, 0x00000000, 0x00000000, 0x443c022c) +#define IOMUXC_PAD_GPIO_IO27_USDHC3_DATA3 IOMUX_PADCFG(0x443c007c, 0x1, 0x443c046c, 0x00000000, 0x443c022c) +#define IOMUXC_PAD_GPIO_IO27_CAN2_RX IOMUX_PADCFG(0x443c007c, 0x2, 0x443c0364, 0x00000001, 0x443c022c) +#define IOMUXC_PAD_GPIO_IO27_MEDIAMIX_DISP_DATA23 IOMUX_PADCFG(0x443c007c, 0x3, 0x00000000, 0x00000000, 0x443c022c) +#define IOMUXC_PAD_GPIO_IO27_TPM6_CH3 IOMUX_PADCFG(0x443c007c, 0x4, 0x00000000, 0x00000000, 0x443c022c) +#define IOMUXC_PAD_GPIO_IO27_JTAG_MUX_TMS IOMUX_PADCFG(0x443c007c, 0x5, 0x443c03dc, 0x00000001, 0x443c022c) +#define IOMUXC_PAD_GPIO_IO27_LPSPI5_PCS1 IOMUX_PADCFG(0x443c007c, 0x6, 0x00000000, 0x00000000, 0x443c022c) +#define IOMUXC_PAD_GPIO_IO27_FLEXIO1_FLEXIO27 IOMUX_PADCFG(0x443c007c, 0x7, 0x443c03c8, 0x00000000, 0x443c022c) +#define IOMUXC_PAD_GPIO_IO28_GPIO2_IO28 IOMUX_PADCFG(0x443c0080, 0x0, 0x00000000, 0x00000000, 0x443c0230) +#define IOMUXC_PAD_GPIO_IO28_LPI2C3_SDA IOMUX_PADCFG(0x443c0080, 0x1, 0x443c03e4, 0x00000001, 0x443c0230) +#define IOMUXC_PAD_GPIO_IO28_FLEXIO1_FLEXIO28 IOMUX_PADCFG(0x443c0080, 0x7, 0x00000000, 0x00000000, 0x443c0230) +#define IOMUXC_PAD_GPIO_IO29_GPIO2_IO29 IOMUX_PADCFG(0x443c0084, 0x0, 0x00000000, 0x00000000, 0x443c0234) +#define IOMUXC_PAD_GPIO_IO29_LPI2C3_SCL IOMUX_PADCFG(0x443c0084, 0x1, 0x443c03e0, 0x00000001, 0x443c0234) +#define IOMUXC_PAD_GPIO_IO29_FLEXIO1_FLEXIO29 IOMUX_PADCFG(0x443c0084, 0x7, 0x00000000, 0x00000000, 0x443c0234) +#define IOMUXC_PAD_CCM_CLKO1_CCMSRCGPCMIX_CLKO1 IOMUX_PADCFG(0x443c0088, 0x0, 0x00000000, 0x00000000, 0x443c0238) +#define IOMUXC_PAD_CCM_CLKO1_FLEXIO1_FLEXIO26 IOMUX_PADCFG(0x443c0088, 0x4, 0x00000000, 0x00000000, 0x443c0238) +#define IOMUXC_PAD_CCM_CLKO1_GPIO3_IO26 IOMUX_PADCFG(0x443c0088, 0x5, 0x00000000, 0x00000000, 0x443c0238) +#define IOMUXC_PAD_CCM_CLKO2_GPIO3_IO27 IOMUX_PADCFG(0x443c008c, 0x5, 0x00000000, 0x00000000, 0x443c023c) +#define IOMUXC_PAD_CCM_CLKO2_CCMSRCGPCMIX_CLKO2 IOMUX_PADCFG(0x443c008c, 0x0, 0x00000000, 0x00000000, 0x443c023c) +#define IOMUXC_PAD_CCM_CLKO2_FLEXIO1_FLEXIO27 IOMUX_PADCFG(0x443c008c, 0x4, 0x443c03c8, 0x00000001, 0x443c023c) +#define IOMUXC_PAD_CCM_CLKO3_CCMSRCGPCMIX_CLKO3 IOMUX_PADCFG(0x443c0090, 0x0, 0x00000000, 0x00000000, 0x443c0240) +#define IOMUXC_PAD_CCM_CLKO3_FLEXIO2_FLEXIO28 IOMUX_PADCFG(0x443c0090, 0x4, 0x00000000, 0x00000000, 0x443c0240) +#define IOMUXC_PAD_CCM_CLKO3_GPIO4_IO28 IOMUX_PADCFG(0x443c0090, 0x5, 0x00000000, 0x00000000, 0x443c0240) +#define IOMUXC_PAD_CCM_CLKO4_CCMSRCGPCMIX_CLKO4 IOMUX_PADCFG(0x443c0094, 0x0, 0x00000000, 0x00000000, 0x443c0244) +#define IOMUXC_PAD_CCM_CLKO4_FLEXIO2_FLEXIO29 IOMUX_PADCFG(0x443c0094, 0x4, 0x00000000, 0x00000000, 0x443c0244) +#define IOMUXC_PAD_CCM_CLKO4_GPIO4_IO29 IOMUX_PADCFG(0x443c0094, 0x5, 0x00000000, 0x00000000, 0x443c0244) +#define IOMUXC_PAD_ENET1_MDC_ENET_QOS_MDC IOMUX_PADCFG(0x443c0098, 0x0, 0x00000000, 0x00000000, 0x443c0248) +#define IOMUXC_PAD_ENET1_MDC_LPUART3_DCB_B IOMUX_PADCFG(0x443c0098, 0x1, 0x00000000, 0x00000000, 0x443c0248) +#define IOMUXC_PAD_ENET1_MDC_I3C2_SCL IOMUX_PADCFG(0x443c0098, 0x2, 0x443c03cc, 0x00000000, 0x443c0248) +#define IOMUXC_PAD_ENET1_MDC_HSIOMIX_OTG_ID1 IOMUX_PADCFG(0x443c0098, 0x3, 0x00000000, 0x00000000, 0x443c0248) +#define IOMUXC_PAD_ENET1_MDC_FLEXIO2_FLEXIO00 IOMUX_PADCFG(0x443c0098, 0x4, 0x00000000, 0x00000000, 0x443c0248) +#define IOMUXC_PAD_ENET1_MDC_GPIO4_IO00 IOMUX_PADCFG(0x443c0098, 0x5, 0x00000000, 0x00000000, 0x443c0248) +#define IOMUXC_PAD_ENET1_MDIO_ENET_QOS_MDIO IOMUX_PADCFG(0x443c009c, 0x0, 0x00000000, 0x00000000, 0x443c024c) +#define IOMUXC_PAD_ENET1_MDIO_LPUART3_RIN_B IOMUX_PADCFG(0x443c009c, 0x1, 0x00000000, 0x00000000, 0x443c024c) +#define IOMUXC_PAD_ENET1_MDIO_I3C2_SDA IOMUX_PADCFG(0x443c009c, 0x2, 0x443c03d0, 0x00000000, 0x443c024c) +#define IOMUXC_PAD_ENET1_MDIO_HSIOMIX_OTG_PWR1 IOMUX_PADCFG(0x443c009c, 0x3, 0x00000000, 0x00000000, 0x443c024c) +#define IOMUXC_PAD_ENET1_MDIO_FLEXIO2_FLEXIO01 IOMUX_PADCFG(0x443c009c, 0x4, 0x00000000, 0x00000000, 0x443c024c) +#define IOMUXC_PAD_ENET1_MDIO_GPIO4_IO01 IOMUX_PADCFG(0x443c009c, 0x5, 0x00000000, 0x00000000, 0x443c024c) +#define IOMUXC_PAD_ENET1_TD3_ENET_QOS_RGMII_TD3 IOMUX_PADCFG(0x443c00a0, 0x0, 0x00000000, 0x00000000, 0x443c0250) +#define IOMUXC_PAD_ENET1_TD3_CAN2_TX IOMUX_PADCFG(0x443c00a0, 0x2, 0x00000000, 0x00000000, 0x443c0250) +#define IOMUXC_PAD_ENET1_TD3_HSIOMIX_OTG_ID2 IOMUX_PADCFG(0x443c00a0, 0x3, 0x00000000, 0x00000000, 0x443c0250) +#define IOMUXC_PAD_ENET1_TD3_FLEXIO2_FLEXIO02 IOMUX_PADCFG(0x443c00a0, 0x4, 0x00000000, 0x00000000, 0x443c0250) +#define IOMUXC_PAD_ENET1_TD3_GPIO4_IO02 IOMUX_PADCFG(0x443c00a0, 0x5, 0x00000000, 0x00000000, 0x443c0250) +#define IOMUXC_PAD_ENET1_TD2_ENET_QOS_RGMII_TD2 IOMUX_PADCFG(0x443c00a4, 0x0, 0x00000000, 0x00000000, 0x443c0254) +#define IOMUXC_PAD_ENET1_TD2_CCM_ENET_QOS_CLOCK_GENERATE_REF_CLK IOMUX_PADCFG(0x443c00a4, 0x1, 0x00000000, 0x00000000, 0x443c0254) +#define IOMUXC_PAD_ENET1_TD2_CAN2_RX IOMUX_PADCFG(0x443c00a4, 0x2, 0x443c0364, 0x00000002, 0x443c0254) +#define IOMUXC_PAD_ENET1_TD2_HSIOMIX_OTG_OC2 IOMUX_PADCFG(0x443c00a4, 0x3, 0x00000000, 0x00000000, 0x443c0254) +#define IOMUXC_PAD_ENET1_TD2_FLEXIO2_FLEXIO03 IOMUX_PADCFG(0x443c00a4, 0x4, 0x00000000, 0x00000000, 0x443c0254) +#define IOMUXC_PAD_ENET1_TD2_GPIO4_IO03 IOMUX_PADCFG(0x443c00a4, 0x5, 0x00000000, 0x00000000, 0x443c0254) +#define IOMUXC_PAD_ENET1_TD1_ENET_QOS_RGMII_TD1 IOMUX_PADCFG(0x443c00a8, 0x0, 0x00000000, 0x00000000, 0x443c0258) +#define IOMUXC_PAD_ENET1_TD1_LPUART3_RTS_B IOMUX_PADCFG(0x443c00a8, 0x1, 0x00000000, 0x00000000, 0x443c0258) +#define IOMUXC_PAD_ENET1_TD1_I3C2_PUR IOMUX_PADCFG(0x443c00a8, 0x2, 0x00000000, 0x00000000, 0x443c0258) +#define IOMUXC_PAD_ENET1_TD1_HSIOMIX_OTG_OC1 IOMUX_PADCFG(0x443c00a8, 0x3, 0x00000000, 0x00000000, 0x443c0258) +#define IOMUXC_PAD_ENET1_TD1_FLEXIO2_FLEXIO04 IOMUX_PADCFG(0x443c00a8, 0x4, 0x00000000, 0x00000000, 0x443c0258) +#define IOMUXC_PAD_ENET1_TD1_GPIO4_IO04 IOMUX_PADCFG(0x443c00a8, 0x5, 0x00000000, 0x00000000, 0x443c0258) +#define IOMUXC_PAD_ENET1_TD1_I3C2_PUR_B IOMUX_PADCFG(0x443c00a8, 0x6, 0x00000000, 0x00000000, 0x443c0258) +#define IOMUXC_PAD_ENET1_TD0_ENET_QOS_RGMII_TD0 IOMUX_PADCFG(0x443c00ac, 0x0, 0x00000000, 0x00000000, 0x443c025c) +#define IOMUXC_PAD_ENET1_TD0_LPUART3_TX IOMUX_PADCFG(0x443c00ac, 0x1, 0x443c041c, 0x00000001, 0x443c025c) +#define IOMUXC_PAD_ENET1_TD0_FLEXIO2_FLEXIO05 IOMUX_PADCFG(0x443c00ac, 0x4, 0x00000000, 0x00000000, 0x443c025c) +#define IOMUXC_PAD_ENET1_TD0_GPIO4_IO05 IOMUX_PADCFG(0x443c00ac, 0x5, 0x00000000, 0x00000000, 0x443c025c) +#define IOMUXC_PAD_ENET1_TX_CTL_ENET_QOS_RGMII_TX_CTL IOMUX_PADCFG(0x443c00b0, 0x0, 0x00000000, 0x00000000, 0x443c0260) +#define IOMUXC_PAD_ENET1_TX_CTL_LPUART3_DTR_B IOMUX_PADCFG(0x443c00b0, 0x1, 0x00000000, 0x00000000, 0x443c0260) +#define IOMUXC_PAD_ENET1_TX_CTL_FLEXIO2_FLEXIO06 IOMUX_PADCFG(0x443c00b0, 0x4, 0x00000000, 0x00000000, 0x443c0260) +#define IOMUXC_PAD_ENET1_TX_CTL_GPIO4_IO06 IOMUX_PADCFG(0x443c00b0, 0x5, 0x00000000, 0x00000000, 0x443c0260) +#define IOMUXC_PAD_ENET1_TXC_CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK IOMUX_PADCFG(0x443c00b4, 0x0, 0x00000000, 0x00000000, 0x443c0264) +#define IOMUXC_PAD_ENET1_TXC_ENET_QOS_TX_ER IOMUX_PADCFG(0x443c00b4, 0x1, 0x00000000, 0x00000000, 0x443c0264) +#define IOMUXC_PAD_ENET1_TXC_FLEXIO2_FLEXIO07 IOMUX_PADCFG(0x443c00b4, 0x4, 0x00000000, 0x00000000, 0x443c0264) +#define IOMUXC_PAD_ENET1_TXC_GPIO4_IO07 IOMUX_PADCFG(0x443c00b4, 0x5, 0x00000000, 0x00000000, 0x443c0264) +#define IOMUXC_PAD_ENET1_RX_CTL_ENET_QOS_RGMII_RX_CTL IOMUX_PADCFG(0x443c00b8, 0x0, 0x00000000, 0x00000000, 0x443c0268) +#define IOMUXC_PAD_ENET1_RX_CTL_LPUART3_DSR_B IOMUX_PADCFG(0x443c00b8, 0x1, 0x00000000, 0x00000000, 0x443c0268) +#define IOMUXC_PAD_ENET1_RX_CTL_HSIOMIX_OTG_PWR2 IOMUX_PADCFG(0x443c00b8, 0x3, 0x00000000, 0x00000000, 0x443c0268) +#define IOMUXC_PAD_ENET1_RX_CTL_FLEXIO2_FLEXIO08 IOMUX_PADCFG(0x443c00b8, 0x4, 0x00000000, 0x00000000, 0x443c0268) +#define IOMUXC_PAD_ENET1_RX_CTL_GPIO4_IO08 IOMUX_PADCFG(0x443c00b8, 0x5, 0x00000000, 0x00000000, 0x443c0268) +#define IOMUXC_PAD_ENET1_RXC_CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK IOMUX_PADCFG(0x443c00bc, 0x0, 0x00000000, 0x00000000, 0x443c026c) +#define IOMUXC_PAD_ENET1_RXC_ENET_QOS_RX_ER IOMUX_PADCFG(0x443c00bc, 0x1, 0x00000000, 0x00000000, 0x443c026c) +#define IOMUXC_PAD_ENET1_RXC_FLEXIO2_FLEXIO09 IOMUX_PADCFG(0x443c00bc, 0x4, 0x00000000, 0x00000000, 0x443c026c) +#define IOMUXC_PAD_ENET1_RXC_GPIO4_IO09 IOMUX_PADCFG(0x443c00bc, 0x5, 0x00000000, 0x00000000, 0x443c026c) +#define IOMUXC_PAD_ENET1_RD0_ENET_QOS_RGMII_RD0 IOMUX_PADCFG(0x443c00c0, 0x0, 0x00000000, 0x00000000, 0x443c0270) +#define IOMUXC_PAD_ENET1_RD0_LPUART3_RX IOMUX_PADCFG(0x443c00c0, 0x1, 0x443c0418, 0x00000001, 0x443c0270) +#define IOMUXC_PAD_ENET1_RD0_FLEXIO2_FLEXIO10 IOMUX_PADCFG(0x443c00c0, 0x4, 0x00000000, 0x00000000, 0x443c0270) +#define IOMUXC_PAD_ENET1_RD0_GPIO4_IO10 IOMUX_PADCFG(0x443c00c0, 0x5, 0x00000000, 0x00000000, 0x443c0270) +#define IOMUXC_PAD_ENET1_RD1_ENET_QOS_RGMII_RD1 IOMUX_PADCFG(0x443c00c4, 0x0, 0x00000000, 0x00000000, 0x443c0274) +#define IOMUXC_PAD_ENET1_RD1_LPUART3_CTS_B IOMUX_PADCFG(0x443c00c4, 0x1, 0x443c0414, 0x00000001, 0x443c0274) +#define IOMUXC_PAD_ENET1_RD1_LPTMR2_ALT1 IOMUX_PADCFG(0x443c00c4, 0x3, 0x443c0408, 0x00000000, 0x443c0274) +#define IOMUXC_PAD_ENET1_RD1_FLEXIO2_FLEXIO11 IOMUX_PADCFG(0x443c00c4, 0x4, 0x00000000, 0x00000000, 0x443c0274) +#define IOMUXC_PAD_ENET1_RD1_GPIO4_IO11 IOMUX_PADCFG(0x443c00c4, 0x5, 0x00000000, 0x00000000, 0x443c0274) +#define IOMUXC_PAD_ENET1_RD2_ENET_QOS_RGMII_RD2 IOMUX_PADCFG(0x443c00c8, 0x0, 0x00000000, 0x00000000, 0x443c0278) +#define IOMUXC_PAD_ENET1_RD2_LPTMR2_ALT2 IOMUX_PADCFG(0x443c00c8, 0x3, 0x443c040c, 0x00000000, 0x443c0278) +#define IOMUXC_PAD_ENET1_RD2_FLEXIO2_FLEXIO12 IOMUX_PADCFG(0x443c00c8, 0x4, 0x00000000, 0x00000000, 0x443c0278) +#define IOMUXC_PAD_ENET1_RD2_GPIO4_IO12 IOMUX_PADCFG(0x443c00c8, 0x5, 0x00000000, 0x00000000, 0x443c0278) +#define IOMUXC_PAD_ENET1_RD3_ENET_QOS_RGMII_RD3 IOMUX_PADCFG(0x443c00cc, 0x0, 0x00000000, 0x00000000, 0x443c027c) +#define IOMUXC_PAD_ENET1_RD3_FLEXSPI1_TESTER_TRIGGER IOMUX_PADCFG(0x443c00cc, 0x2, 0x00000000, 0x00000000, 0x443c027c) +#define IOMUXC_PAD_ENET1_RD3_LPTMR2_ALT3 IOMUX_PADCFG(0x443c00cc, 0x3, 0x443c0410, 0x00000000, 0x443c027c) +#define IOMUXC_PAD_ENET1_RD3_FLEXIO2_FLEXIO13 IOMUX_PADCFG(0x443c00cc, 0x4, 0x00000000, 0x00000000, 0x443c027c) +#define IOMUXC_PAD_ENET1_RD3_GPIO4_IO13 IOMUX_PADCFG(0x443c00cc, 0x5, 0x00000000, 0x00000000, 0x443c027c) +#define IOMUXC_PAD_ENET2_MDC_ENET1_MDC IOMUX_PADCFG(0x443c00d0, 0x0, 0x00000000, 0x00000000, 0x443c0280) +#define IOMUXC_PAD_ENET2_MDC_LPUART4_DCB_B IOMUX_PADCFG(0x443c00d0, 0x1, 0x00000000, 0x00000000, 0x443c0280) +#define IOMUXC_PAD_ENET2_MDC_SAI2_RX_SYNC IOMUX_PADCFG(0x443c00d0, 0x2, 0x00000000, 0x00000000, 0x443c0280) +#define IOMUXC_PAD_ENET2_MDC_FLEXIO2_FLEXIO14 IOMUX_PADCFG(0x443c00d0, 0x4, 0x00000000, 0x00000000, 0x443c0280) +#define IOMUXC_PAD_ENET2_MDC_GPIO4_IO14 IOMUX_PADCFG(0x443c00d0, 0x5, 0x00000000, 0x00000000, 0x443c0280) +#define IOMUXC_PAD_ENET2_MDIO_ENET1_MDIO IOMUX_PADCFG(0x443c00d4, 0x0, 0x00000000, 0x00000000, 0x443c0284) +#define IOMUXC_PAD_ENET2_MDIO_LPUART4_RIN_B IOMUX_PADCFG(0x443c00d4, 0x1, 0x00000000, 0x00000000, 0x443c0284) +#define IOMUXC_PAD_ENET2_MDIO_SAI2_RX_BCLK IOMUX_PADCFG(0x443c00d4, 0x2, 0x00000000, 0x00000000, 0x443c0284) +#define IOMUXC_PAD_ENET2_MDIO_FLEXIO2_FLEXIO15 IOMUX_PADCFG(0x443c00d4, 0x4, 0x00000000, 0x00000000, 0x443c0284) +#define IOMUXC_PAD_ENET2_MDIO_GPIO4_IO15 IOMUX_PADCFG(0x443c00d4, 0x5, 0x00000000, 0x00000000, 0x443c0284) +#define IOMUXC_PAD_ENET2_TD3_SAI2_RX_DATA00 IOMUX_PADCFG(0x443c00d8, 0x2, 0x00000000, 0x00000000, 0x443c0288) +#define IOMUXC_PAD_ENET2_TD3_FLEXIO2_FLEXIO16 IOMUX_PADCFG(0x443c00d8, 0x4, 0x00000000, 0x00000000, 0x443c0288) +#define IOMUXC_PAD_ENET2_TD3_GPIO4_IO16 IOMUX_PADCFG(0x443c00d8, 0x5, 0x00000000, 0x00000000, 0x443c0288) +#define IOMUXC_PAD_ENET2_TD3_ENET1_RGMII_TD3 IOMUX_PADCFG(0x443c00d8, 0x0, 0x00000000, 0x00000000, 0x443c0288) +#define IOMUXC_PAD_ENET2_TD2_ENET1_RGMII_TD2 IOMUX_PADCFG(0x443c00dc, 0x0, 0x00000000, 0x00000000, 0x443c028c) +#define IOMUXC_PAD_ENET2_TD2_ENET1_TX_CLK IOMUX_PADCFG(0x443c00dc, 0x1, 0x00000000, 0x00000000, 0x443c028c) +#define IOMUXC_PAD_ENET2_TD2_SAI2_RX_DATA01 IOMUX_PADCFG(0x443c00dc, 0x2, 0x00000000, 0x00000000, 0x443c028c) +#define IOMUXC_PAD_ENET2_TD2_FLEXIO2_FLEXIO17 IOMUX_PADCFG(0x443c00dc, 0x4, 0x00000000, 0x00000000, 0x443c028c) +#define IOMUXC_PAD_ENET2_TD2_GPIO4_IO17 IOMUX_PADCFG(0x443c00dc, 0x5, 0x00000000, 0x00000000, 0x443c028c) +#define IOMUXC_PAD_ENET2_TD1_ENET1_RGMII_TD1 IOMUX_PADCFG(0x443c00e0, 0x0, 0x00000000, 0x00000000, 0x443c0290) +#define IOMUXC_PAD_ENET2_TD1_LPUART4_RTS_B IOMUX_PADCFG(0x443c00e0, 0x1, 0x00000000, 0x00000000, 0x443c0290) +#define IOMUXC_PAD_ENET2_TD1_SAI2_RX_DATA02 IOMUX_PADCFG(0x443c00e0, 0x2, 0x00000000, 0x00000000, 0x443c0290) +#define IOMUXC_PAD_ENET2_TD1_FLEXIO2_FLEXIO18 IOMUX_PADCFG(0x443c00e0, 0x4, 0x00000000, 0x00000000, 0x443c0290) +#define IOMUXC_PAD_ENET2_TD1_GPIO4_IO18 IOMUX_PADCFG(0x443c00e0, 0x5, 0x00000000, 0x00000000, 0x443c0290) +#define IOMUXC_PAD_ENET2_TD0_ENET1_RGMII_TD0 IOMUX_PADCFG(0x443c00e4, 0x0, 0x00000000, 0x00000000, 0x443c0294) +#define IOMUXC_PAD_ENET2_TD0_LPUART4_TX IOMUX_PADCFG(0x443c00e4, 0x1, 0x443c0428, 0x00000001, 0x443c0294) +#define IOMUXC_PAD_ENET2_TD0_SAI2_RX_DATA03 IOMUX_PADCFG(0x443c00e4, 0x2, 0x00000000, 0x00000000, 0x443c0294) +#define IOMUXC_PAD_ENET2_TD0_FLEXIO2_FLEXIO19 IOMUX_PADCFG(0x443c00e4, 0x4, 0x00000000, 0x00000000, 0x443c0294) +#define IOMUXC_PAD_ENET2_TD0_GPIO4_IO19 IOMUX_PADCFG(0x443c00e4, 0x5, 0x00000000, 0x00000000, 0x443c0294) +#define IOMUXC_PAD_ENET2_TX_CTL_ENET1_RGMII_TX_CTL IOMUX_PADCFG(0x443c00e8, 0x0, 0x00000000, 0x00000000, 0x443c0298) +#define IOMUXC_PAD_ENET2_TX_CTL_LPUART4_DTR_B IOMUX_PADCFG(0x443c00e8, 0x1, 0x00000000, 0x00000000, 0x443c0298) +#define IOMUXC_PAD_ENET2_TX_CTL_SAI2_TX_SYNC IOMUX_PADCFG(0x443c00e8, 0x2, 0x00000000, 0x00000000, 0x443c0298) +#define IOMUXC_PAD_ENET2_TX_CTL_FLEXIO2_FLEXIO20 IOMUX_PADCFG(0x443c00e8, 0x4, 0x00000000, 0x00000000, 0x443c0298) +#define IOMUXC_PAD_ENET2_TX_CTL_GPIO4_IO20 IOMUX_PADCFG(0x443c00e8, 0x5, 0x00000000, 0x00000000, 0x443c0298) +#define IOMUXC_PAD_ENET2_TXC_ENET1_RGMII_TXC IOMUX_PADCFG(0x443c00ec, 0x0, 0x00000000, 0x00000000, 0x443c029c) +#define IOMUXC_PAD_ENET2_TXC_ENET1_TX_ER IOMUX_PADCFG(0x443c00ec, 0x1, 0x00000000, 0x00000000, 0x443c029c) +#define IOMUXC_PAD_ENET2_TXC_SAI2_TX_BCLK IOMUX_PADCFG(0x443c00ec, 0x2, 0x00000000, 0x00000000, 0x443c029c) +#define IOMUXC_PAD_ENET2_TXC_FLEXIO2_FLEXIO21 IOMUX_PADCFG(0x443c00ec, 0x4, 0x00000000, 0x00000000, 0x443c029c) +#define IOMUXC_PAD_ENET2_TXC_GPIO4_IO21 IOMUX_PADCFG(0x443c00ec, 0x5, 0x00000000, 0x00000000, 0x443c029c) +#define IOMUXC_PAD_ENET2_RX_CTL_ENET1_RGMII_RX_CTL IOMUX_PADCFG(0x443c00f0, 0x0, 0x00000000, 0x00000000, 0x443c02a0) +#define IOMUXC_PAD_ENET2_RX_CTL_LPUART4_DSR_B IOMUX_PADCFG(0x443c00f0, 0x1, 0x00000000, 0x00000000, 0x443c02a0) +#define IOMUXC_PAD_ENET2_RX_CTL_SAI2_TX_DATA00 IOMUX_PADCFG(0x443c00f0, 0x2, 0x00000000, 0x00000000, 0x443c02a0) +#define IOMUXC_PAD_ENET2_RX_CTL_FLEXIO2_FLEXIO22 IOMUX_PADCFG(0x443c00f0, 0x4, 0x00000000, 0x00000000, 0x443c02a0) +#define IOMUXC_PAD_ENET2_RX_CTL_GPIO4_IO22 IOMUX_PADCFG(0x443c00f0, 0x5, 0x00000000, 0x00000000, 0x443c02a0) +#define IOMUXC_PAD_ENET2_RXC_ENET1_RGMII_RXC IOMUX_PADCFG(0x443c00f4, 0x0, 0x00000000, 0x00000000, 0x443c02a4) +#define IOMUXC_PAD_ENET2_RXC_ENET1_RX_ER IOMUX_PADCFG(0x443c00f4, 0x1, 0x00000000, 0x00000000, 0x443c02a4) +#define IOMUXC_PAD_ENET2_RXC_SAI2_TX_DATA01 IOMUX_PADCFG(0x443c00f4, 0x2, 0x00000000, 0x00000000, 0x443c02a4) +#define IOMUXC_PAD_ENET2_RXC_FLEXIO2_FLEXIO23 IOMUX_PADCFG(0x443c00f4, 0x4, 0x00000000, 0x00000000, 0x443c02a4) +#define IOMUXC_PAD_ENET2_RXC_GPIO4_IO23 IOMUX_PADCFG(0x443c00f4, 0x5, 0x00000000, 0x00000000, 0x443c02a4) +#define IOMUXC_PAD_ENET2_RD0_ENET1_RGMII_RD0 IOMUX_PADCFG(0x443c00f8, 0x0, 0x00000000, 0x00000000, 0x443c02a8) +#define IOMUXC_PAD_ENET2_RD0_LPUART4_RX IOMUX_PADCFG(0x443c00f8, 0x1, 0x443c0424, 0x00000001, 0x443c02a8) +#define IOMUXC_PAD_ENET2_RD0_SAI2_TX_DATA02 IOMUX_PADCFG(0x443c00f8, 0x2, 0x00000000, 0x00000000, 0x443c02a8) +#define IOMUXC_PAD_ENET2_RD0_FLEXIO2_FLEXIO24 IOMUX_PADCFG(0x443c00f8, 0x4, 0x00000000, 0x00000000, 0x443c02a8) +#define IOMUXC_PAD_ENET2_RD0_GPIO4_IO24 IOMUX_PADCFG(0x443c00f8, 0x5, 0x00000000, 0x00000000, 0x443c02a8) +#define IOMUXC_PAD_ENET2_RD1_ENET1_RGMII_RD1 IOMUX_PADCFG(0x443c00fc, 0x0, 0x00000000, 0x00000000, 0x443c02ac) +#define IOMUXC_PAD_ENET2_RD1_SPDIF_IN IOMUX_PADCFG(0x443c00fc, 0x1, 0x443c0454, 0x00000001, 0x443c02ac) +#define IOMUXC_PAD_ENET2_RD1_SAI2_TX_DATA03 IOMUX_PADCFG(0x443c00fc, 0x2, 0x00000000, 0x00000000, 0x443c02ac) +#define IOMUXC_PAD_ENET2_RD1_FLEXIO2_FLEXIO25 IOMUX_PADCFG(0x443c00fc, 0x4, 0x00000000, 0x00000000, 0x443c02ac) +#define IOMUXC_PAD_ENET2_RD1_GPIO4_IO25 IOMUX_PADCFG(0x443c00fc, 0x5, 0x00000000, 0x00000000, 0x443c02ac) +#define IOMUXC_PAD_ENET2_RD2_ENET1_RGMII_RD2 IOMUX_PADCFG(0x443c0100, 0x0, 0x00000000, 0x00000000, 0x443c02b0) +#define IOMUXC_PAD_ENET2_RD2_LPUART4_CTS_B IOMUX_PADCFG(0x443c0100, 0x1, 0x443c0420, 0x00000001, 0x443c02b0) +#define IOMUXC_PAD_ENET2_RD2_SAI2_MCLK IOMUX_PADCFG(0x443c0100, 0x2, 0x00000000, 0x00000000, 0x443c02b0) +#define IOMUXC_PAD_ENET2_RD2_MQS2_RIGHT IOMUX_PADCFG(0x443c0100, 0x3, 0x00000000, 0x00000000, 0x443c02b0) +#define IOMUXC_PAD_ENET2_RD2_FLEXIO2_FLEXIO26 IOMUX_PADCFG(0x443c0100, 0x4, 0x00000000, 0x00000000, 0x443c02b0) +#define IOMUXC_PAD_ENET2_RD2_GPIO4_IO26 IOMUX_PADCFG(0x443c0100, 0x5, 0x00000000, 0x00000000, 0x443c02b0) +#define IOMUXC_PAD_ENET2_RD3_ENET1_RGMII_RD3 IOMUX_PADCFG(0x443c0104, 0x0, 0x00000000, 0x00000000, 0x443c02b4) +#define IOMUXC_PAD_ENET2_RD3_SPDIF_OUT IOMUX_PADCFG(0x443c0104, 0x1, 0x00000000, 0x00000000, 0x443c02b4) +#define IOMUXC_PAD_ENET2_RD3_SPDIF_IN IOMUX_PADCFG(0x443c0104, 0x2, 0x443c0454, 0x00000002, 0x443c02b4) +#define IOMUXC_PAD_ENET2_RD3_MQS2_LEFT IOMUX_PADCFG(0x443c0104, 0x3, 0x00000000, 0x00000000, 0x443c02b4) +#define IOMUXC_PAD_ENET2_RD3_FLEXIO2_FLEXIO27 IOMUX_PADCFG(0x443c0104, 0x4, 0x00000000, 0x00000000, 0x443c02b4) +#define IOMUXC_PAD_ENET2_RD3_GPIO4_IO27 IOMUX_PADCFG(0x443c0104, 0x5, 0x00000000, 0x00000000, 0x443c02b4) +#define IOMUXC_PAD_SD1_CLK_FLEXIO1_FLEXIO08 IOMUX_PADCFG(0x443c0108, 0x4, 0x443c038c, 0x00000001, 0x443c02b8) +#define IOMUXC_PAD_SD1_CLK_GPIO3_IO08 IOMUX_PADCFG(0x443c0108, 0x5, 0x00000000, 0x00000000, 0x443c02b8) +#define IOMUXC_PAD_SD1_CLK_USDHC1_CLK IOMUX_PADCFG(0x443c0108, 0x0, 0x00000000, 0x00000000, 0x443c02b8) +#define IOMUXC_PAD_SD1_CMD_USDHC1_CMD IOMUX_PADCFG(0x443c010c, 0x0, 0x00000000, 0x00000000, 0x443c02bc) +#define IOMUXC_PAD_SD1_CMD_FLEXIO1_FLEXIO09 IOMUX_PADCFG(0x443c010c, 0x4, 0x443c0390, 0x00000001, 0x443c02bc) +#define IOMUXC_PAD_SD1_CMD_GPIO3_IO09 IOMUX_PADCFG(0x443c010c, 0x5, 0x00000000, 0x00000000, 0x443c02bc) +#define IOMUXC_PAD_SD1_DATA0_USDHC1_DATA0 IOMUX_PADCFG(0x443c0110, 0x0, 0x00000000, 0x00000000, 0x443c02c0) +#define IOMUXC_PAD_SD1_DATA0_FLEXIO1_FLEXIO10 IOMUX_PADCFG(0x443c0110, 0x4, 0x443c0394, 0x00000001, 0x443c02c0) +#define IOMUXC_PAD_SD1_DATA0_GPIO3_IO10 IOMUX_PADCFG(0x443c0110, 0x5, 0x00000000, 0x00000000, 0x443c02c0) +#define IOMUXC_PAD_SD1_DATA1_USDHC1_DATA1 IOMUX_PADCFG(0x443c0114, 0x0, 0x00000000, 0x00000000, 0x443c02c4) +#define IOMUXC_PAD_SD1_DATA1_FLEXIO1_FLEXIO11 IOMUX_PADCFG(0x443c0114, 0x4, 0x443c0398, 0x00000001, 0x443c02c4) +#define IOMUXC_PAD_SD1_DATA1_GPIO3_IO11 IOMUX_PADCFG(0x443c0114, 0x5, 0x00000000, 0x00000000, 0x443c02c4) +#define IOMUXC_PAD_SD1_DATA1_CCMSRCGPCMIX_INT_BOOT IOMUX_PADCFG(0x443c0114, 0x6, 0x00000000, 0x00000000, 0x443c02c4) +#define IOMUXC_PAD_SD1_DATA2_USDHC1_DATA2 IOMUX_PADCFG(0x443c0118, 0x0, 0x00000000, 0x00000000, 0x443c02c8) +#define IOMUXC_PAD_SD1_DATA2_FLEXIO1_FLEXIO12 IOMUX_PADCFG(0x443c0118, 0x4, 0x00000000, 0x00000000, 0x443c02c8) +#define IOMUXC_PAD_SD1_DATA2_GPIO3_IO12 IOMUX_PADCFG(0x443c0118, 0x5, 0x00000000, 0x00000000, 0x443c02c8) +#define IOMUXC_PAD_SD1_DATA2_CCMSRCGPCMIX_PMIC_READY IOMUX_PADCFG(0x443c0118, 0x6, 0x00000000, 0x00000000, 0x443c02c8) +#define IOMUXC_PAD_SD1_DATA3_USDHC1_DATA3 IOMUX_PADCFG(0x443c011c, 0x0, 0x00000000, 0x00000000, 0x443c02cc) +#define IOMUXC_PAD_SD1_DATA3_FLEXSPI1_A_SS1_B IOMUX_PADCFG(0x443c011c, 0x1, 0x00000000, 0x00000000, 0x443c02cc) +#define IOMUXC_PAD_SD1_DATA3_FLEXIO1_FLEXIO13 IOMUX_PADCFG(0x443c011c, 0x4, 0x443c039c, 0x00000001, 0x443c02cc) +#define IOMUXC_PAD_SD1_DATA3_GPIO3_IO13 IOMUX_PADCFG(0x443c011c, 0x5, 0x00000000, 0x00000000, 0x443c02cc) +#define IOMUXC_PAD_SD1_DATA4_USDHC1_DATA4 IOMUX_PADCFG(0x443c0120, 0x0, 0x00000000, 0x00000000, 0x443c02d0) +#define IOMUXC_PAD_SD1_DATA4_FLEXSPI1_A_DATA04 IOMUX_PADCFG(0x443c0120, 0x1, 0x00000000, 0x00000000, 0x443c02d0) +#define IOMUXC_PAD_SD1_DATA4_FLEXIO1_FLEXIO14 IOMUX_PADCFG(0x443c0120, 0x4, 0x443c03a0, 0x00000001, 0x443c02d0) +#define IOMUXC_PAD_SD1_DATA4_GPIO3_IO14 IOMUX_PADCFG(0x443c0120, 0x5, 0x00000000, 0x00000000, 0x443c02d0) +#define IOMUXC_PAD_SD1_DATA5_USDHC1_DATA5 IOMUX_PADCFG(0x443c0124, 0x0, 0x00000000, 0x00000000, 0x443c02d4) +#define IOMUXC_PAD_SD1_DATA5_FLEXSPI1_A_DATA05 IOMUX_PADCFG(0x443c0124, 0x1, 0x00000000, 0x00000000, 0x443c02d4) +#define IOMUXC_PAD_SD1_DATA5_USDHC1_RESET_B IOMUX_PADCFG(0x443c0124, 0x2, 0x00000000, 0x00000000, 0x443c02d4) +#define IOMUXC_PAD_SD1_DATA5_FLEXIO1_FLEXIO15 IOMUX_PADCFG(0x443c0124, 0x4, 0x443c03a4, 0x00000001, 0x443c02d4) +#define IOMUXC_PAD_SD1_DATA5_GPIO3_IO15 IOMUX_PADCFG(0x443c0124, 0x5, 0x00000000, 0x00000000, 0x443c02d4) +#define IOMUXC_PAD_SD1_DATA6_USDHC1_DATA6 IOMUX_PADCFG(0x443c0128, 0x0, 0x00000000, 0x00000000, 0x443c02d8) +#define IOMUXC_PAD_SD1_DATA6_FLEXSPI1_A_DATA06 IOMUX_PADCFG(0x443c0128, 0x1, 0x00000000, 0x00000000, 0x443c02d8) +#define IOMUXC_PAD_SD1_DATA6_USDHC1_CD_B IOMUX_PADCFG(0x443c0128, 0x2, 0x00000000, 0x00000000, 0x443c02d8) +#define IOMUXC_PAD_SD1_DATA6_FLEXIO1_FLEXIO16 IOMUX_PADCFG(0x443c0128, 0x4, 0x443c03a8, 0x00000001, 0x443c02d8) +#define IOMUXC_PAD_SD1_DATA6_GPIO3_IO16 IOMUX_PADCFG(0x443c0128, 0x5, 0x00000000, 0x00000000, 0x443c02d8) +#define IOMUXC_PAD_SD1_DATA7_USDHC1_DATA7 IOMUX_PADCFG(0x443c012c, 0x0, 0x00000000, 0x00000000, 0x443c02dc) +#define IOMUXC_PAD_SD1_DATA7_FLEXSPI1_A_DATA07 IOMUX_PADCFG(0x443c012c, 0x1, 0x00000000, 0x00000000, 0x443c02dc) +#define IOMUXC_PAD_SD1_DATA7_USDHC1_WP IOMUX_PADCFG(0x443c012c, 0x2, 0x00000000, 0x00000000, 0x443c02dc) +#define IOMUXC_PAD_SD1_DATA7_FLEXIO1_FLEXIO17 IOMUX_PADCFG(0x443c012c, 0x4, 0x443c03ac, 0x00000001, 0x443c02dc) +#define IOMUXC_PAD_SD1_DATA7_GPIO3_IO17 IOMUX_PADCFG(0x443c012c, 0x5, 0x00000000, 0x00000000, 0x443c02dc) +#define IOMUXC_PAD_SD1_STROBE_USDHC1_STROBE IOMUX_PADCFG(0x443c0130, 0x0, 0x00000000, 0x00000000, 0x443c02e0) +#define IOMUXC_PAD_SD1_STROBE_FLEXSPI1_A_DQS IOMUX_PADCFG(0x443c0130, 0x1, 0x00000000, 0x00000000, 0x443c02e0) +#define IOMUXC_PAD_SD1_STROBE_FLEXIO1_FLEXIO18 IOMUX_PADCFG(0x443c0130, 0x4, 0x443c03b0, 0x00000001, 0x443c02e0) +#define IOMUXC_PAD_SD1_STROBE_GPIO3_IO18 IOMUX_PADCFG(0x443c0130, 0x5, 0x00000000, 0x00000000, 0x443c02e0) +#define IOMUXC_PAD_SD2_VSELECT_USDHC2_VSELECT IOMUX_PADCFG(0x443c0134, 0x0, 0x00000000, 0x00000000, 0x443c02e4) +#define IOMUXC_PAD_SD2_VSELECT_USDHC2_WP IOMUX_PADCFG(0x443c0134, 0x1, 0x00000000, 0x00000000, 0x443c02e4) +#define IOMUXC_PAD_SD2_VSELECT_LPTMR2_ALT3 IOMUX_PADCFG(0x443c0134, 0x2, 0x443c0410, 0x00000001, 0x443c02e4) +#define IOMUXC_PAD_SD2_VSELECT_FLEXIO1_FLEXIO19 IOMUX_PADCFG(0x443c0134, 0x4, 0x00000000, 0x00000000, 0x443c02e4) +#define IOMUXC_PAD_SD2_VSELECT_GPIO3_IO19 IOMUX_PADCFG(0x443c0134, 0x5, 0x00000000, 0x00000000, 0x443c02e4) +#define IOMUXC_PAD_SD2_VSELECT_CCMSRCGPCMIX_EXT_CLK1 IOMUX_PADCFG(0x443c0134, 0x6, 0x443c0368, 0x00000000, 0x443c02e4) +#define IOMUXC_PAD_SD3_CLK_USDHC3_CLK IOMUX_PADCFG(0x443c0138, 0x0, 0x443c0458, 0x00000001, 0x443c02e8) +#define IOMUXC_PAD_SD3_CLK_FLEXSPI1_A_SCLK IOMUX_PADCFG(0x443c0138, 0x1, 0x00000000, 0x00000000, 0x443c02e8) +#define IOMUXC_PAD_SD3_CLK_FLEXIO1_FLEXIO20 IOMUX_PADCFG(0x443c0138, 0x4, 0x443c03b4, 0x00000001, 0x443c02e8) +#define IOMUXC_PAD_SD3_CLK_GPIO3_IO20 IOMUX_PADCFG(0x443c0138, 0x5, 0x00000000, 0x00000000, 0x443c02e8) +#define IOMUXC_PAD_SD3_CMD_USDHC3_CMD IOMUX_PADCFG(0x443c013c, 0x0, 0x443c045c, 0x00000001, 0x443c02ec) +#define IOMUXC_PAD_SD3_CMD_FLEXSPI1_A_SS0_B IOMUX_PADCFG(0x443c013c, 0x1, 0x00000000, 0x00000000, 0x443c02ec) +#define IOMUXC_PAD_SD3_CMD_FLEXIO1_FLEXIO21 IOMUX_PADCFG(0x443c013c, 0x4, 0x00000000, 0x00000000, 0x443c02ec) +#define IOMUXC_PAD_SD3_CMD_GPIO3_IO21 IOMUX_PADCFG(0x443c013c, 0x5, 0x00000000, 0x00000000, 0x443c02ec) +#define IOMUXC_PAD_SD3_DATA0_USDHC3_DATA0 IOMUX_PADCFG(0x443c0140, 0x0, 0x443c0460, 0x00000001, 0x443c02f0) +#define IOMUXC_PAD_SD3_DATA0_FLEXSPI1_A_DATA00 IOMUX_PADCFG(0x443c0140, 0x1, 0x00000000, 0x00000000, 0x443c02f0) +#define IOMUXC_PAD_SD3_DATA0_FLEXIO1_FLEXIO22 IOMUX_PADCFG(0x443c0140, 0x4, 0x443c03b8, 0x00000001, 0x443c02f0) +#define IOMUXC_PAD_SD3_DATA0_GPIO3_IO22 IOMUX_PADCFG(0x443c0140, 0x5, 0x00000000, 0x00000000, 0x443c02f0) +#define IOMUXC_PAD_SD3_DATA1_USDHC3_DATA1 IOMUX_PADCFG(0x443c0144, 0x0, 0x443c0464, 0x00000001, 0x443c02f4) +#define IOMUXC_PAD_SD3_DATA1_FLEXSPI1_A_DATA01 IOMUX_PADCFG(0x443c0144, 0x1, 0x00000000, 0x00000000, 0x443c02f4) +#define IOMUXC_PAD_SD3_DATA1_FLEXIO1_FLEXIO23 IOMUX_PADCFG(0x443c0144, 0x4, 0x443c03bc, 0x00000001, 0x443c02f4) +#define IOMUXC_PAD_SD3_DATA1_GPIO3_IO23 IOMUX_PADCFG(0x443c0144, 0x5, 0x00000000, 0x00000000, 0x443c02f4) +#define IOMUXC_PAD_SD3_DATA2_USDHC3_DATA2 IOMUX_PADCFG(0x443c0148, 0x0, 0x443c0468, 0x00000001, 0x443c02f8) +#define IOMUXC_PAD_SD3_DATA2_FLEXSPI1_A_DATA02 IOMUX_PADCFG(0x443c0148, 0x1, 0x00000000, 0x00000000, 0x443c02f8) +#define IOMUXC_PAD_SD3_DATA2_FLEXIO1_FLEXIO24 IOMUX_PADCFG(0x443c0148, 0x4, 0x443c03c0, 0x00000001, 0x443c02f8) +#define IOMUXC_PAD_SD3_DATA2_GPIO3_IO24 IOMUX_PADCFG(0x443c0148, 0x5, 0x00000000, 0x00000000, 0x443c02f8) +#define IOMUXC_PAD_SD3_DATA3_USDHC3_DATA3 IOMUX_PADCFG(0x443c014c, 0x0, 0x443c046c, 0x00000001, 0x443c02fc) +#define IOMUXC_PAD_SD3_DATA3_FLEXSPI1_A_DATA03 IOMUX_PADCFG(0x443c014c, 0x1, 0x00000000, 0x00000000, 0x443c02fc) +#define IOMUXC_PAD_SD3_DATA3_FLEXIO1_FLEXIO25 IOMUX_PADCFG(0x443c014c, 0x4, 0x443c03c4, 0x00000001, 0x443c02fc) +#define IOMUXC_PAD_SD3_DATA3_GPIO3_IO25 IOMUX_PADCFG(0x443c014c, 0x5, 0x00000000, 0x00000000, 0x443c02fc) +#define IOMUXC_PAD_SD2_CD_B_USDHC2_CD_B IOMUX_PADCFG(0x443c0150, 0x0, 0x00000000, 0x00000000, 0x443c0300) +#define IOMUXC_PAD_SD2_CD_B_ENET_QOS_1588_EVENT0_IN IOMUX_PADCFG(0x443c0150, 0x1, 0x00000000, 0x00000000, 0x443c0300) +#define IOMUXC_PAD_SD2_CD_B_I3C2_SCL IOMUX_PADCFG(0x443c0150, 0x2, 0x443c03cc, 0x00000001, 0x443c0300) +#define IOMUXC_PAD_SD2_CD_B_FLEXIO1_FLEXIO00 IOMUX_PADCFG(0x443c0150, 0x4, 0x443c036c, 0x00000001, 0x443c0300) +#define IOMUXC_PAD_SD2_CD_B_GPIO3_IO00 IOMUX_PADCFG(0x443c0150, 0x5, 0x00000000, 0x00000000, 0x443c0300) +#define IOMUXC_PAD_SD2_CLK_USDHC2_CLK IOMUX_PADCFG(0x443c0154, 0x0, 0x00000000, 0x00000000, 0x443c0304) +#define IOMUXC_PAD_SD2_CLK_ENET_QOS_1588_EVENT0_OUT IOMUX_PADCFG(0x443c0154, 0x1, 0x00000000, 0x00000000, 0x443c0304) +#define IOMUXC_PAD_SD2_CLK_I3C2_SDA IOMUX_PADCFG(0x443c0154, 0x2, 0x443c03d0, 0x00000001, 0x443c0304) +#define IOMUXC_PAD_SD2_CLK_FLEXIO1_FLEXIO01 IOMUX_PADCFG(0x443c0154, 0x4, 0x443c0370, 0x00000001, 0x443c0304) +#define IOMUXC_PAD_SD2_CLK_GPIO3_IO01 IOMUX_PADCFG(0x443c0154, 0x5, 0x00000000, 0x00000000, 0x443c0304) +#define IOMUXC_PAD_SD2_CLK_CCMSRCGPCMIX_OBSERVE0 IOMUX_PADCFG(0x443c0154, 0x6, 0x00000000, 0x00000000, 0x443c0304) +#define IOMUXC_PAD_SD2_CMD_USDHC2_CMD IOMUX_PADCFG(0x443c0158, 0x0, 0x00000000, 0x00000000, 0x443c0308) +#define IOMUXC_PAD_SD2_CMD_ENET1_1588_EVENT0_IN IOMUX_PADCFG(0x443c0158, 0x1, 0x00000000, 0x00000000, 0x443c0308) +#define IOMUXC_PAD_SD2_CMD_I3C2_PUR IOMUX_PADCFG(0x443c0158, 0x2, 0x00000000, 0x00000000, 0x443c0308) +#define IOMUXC_PAD_SD2_CMD_I3C2_PUR_B IOMUX_PADCFG(0x443c0158, 0x3, 0x00000000, 0x00000000, 0x443c0308) +#define IOMUXC_PAD_SD2_CMD_FLEXIO1_FLEXIO02 IOMUX_PADCFG(0x443c0158, 0x4, 0x443c0374, 0x00000001, 0x443c0308) +#define IOMUXC_PAD_SD2_CMD_GPIO3_IO02 IOMUX_PADCFG(0x443c0158, 0x5, 0x00000000, 0x00000000, 0x443c0308) +#define IOMUXC_PAD_SD2_CMD_CCMSRCGPCMIX_OBSERVE1 IOMUX_PADCFG(0x443c0158, 0x6, 0x00000000, 0x00000000, 0x443c0308) +#define IOMUXC_PAD_SD2_DATA0_USDHC2_DATA0 IOMUX_PADCFG(0x443c015c, 0x0, 0x00000000, 0x00000000, 0x443c030c) +#define IOMUXC_PAD_SD2_DATA0_ENET1_1588_EVENT0_OUT IOMUX_PADCFG(0x443c015c, 0x1, 0x00000000, 0x00000000, 0x443c030c) +#define IOMUXC_PAD_SD2_DATA0_CAN2_TX IOMUX_PADCFG(0x443c015c, 0x2, 0x00000000, 0x00000000, 0x443c030c) +#define IOMUXC_PAD_SD2_DATA0_FLEXIO1_FLEXIO03 IOMUX_PADCFG(0x443c015c, 0x4, 0x443c0378, 0x00000001, 0x443c030c) +#define IOMUXC_PAD_SD2_DATA0_GPIO3_IO03 IOMUX_PADCFG(0x443c015c, 0x5, 0x00000000, 0x00000000, 0x443c030c) +#define IOMUXC_PAD_SD2_DATA0_CCMSRCGPCMIX_OBSERVE2 IOMUX_PADCFG(0x443c015c, 0x6, 0x00000000, 0x00000000, 0x443c030c) +#define IOMUXC_PAD_SD2_DATA1_USDHC2_DATA1 IOMUX_PADCFG(0x443c0160, 0x0, 0x00000000, 0x00000000, 0x443c0310) +#define IOMUXC_PAD_SD2_DATA1_ENET1_1588_EVENT1_IN IOMUX_PADCFG(0x443c0160, 0x1, 0x00000000, 0x00000000, 0x443c0310) +#define IOMUXC_PAD_SD2_DATA1_CAN2_RX IOMUX_PADCFG(0x443c0160, 0x2, 0x443c0364, 0x00000003, 0x443c0310) +#define IOMUXC_PAD_SD2_DATA1_FLEXIO1_FLEXIO04 IOMUX_PADCFG(0x443c0160, 0x4, 0x443c037c, 0x00000001, 0x443c0310) +#define IOMUXC_PAD_SD2_DATA1_GPIO3_IO04 IOMUX_PADCFG(0x443c0160, 0x5, 0x00000000, 0x00000000, 0x443c0310) +#define IOMUXC_PAD_SD2_DATA1_CCMSRCGPCMIX_WAIT IOMUX_PADCFG(0x443c0160, 0x6, 0x00000000, 0x00000000, 0x443c0310) +#define IOMUXC_PAD_SD2_DATA2_USDHC2_DATA2 IOMUX_PADCFG(0x443c0164, 0x0, 0x00000000, 0x00000000, 0x443c0314) +#define IOMUXC_PAD_SD2_DATA2_ENET1_1588_EVENT1_OUT IOMUX_PADCFG(0x443c0164, 0x1, 0x00000000, 0x00000000, 0x443c0314) +#define IOMUXC_PAD_SD2_DATA2_MQS2_RIGHT IOMUX_PADCFG(0x443c0164, 0x2, 0x00000000, 0x00000000, 0x443c0314) +#define IOMUXC_PAD_SD2_DATA2_FLEXIO1_FLEXIO05 IOMUX_PADCFG(0x443c0164, 0x4, 0x443c0380, 0x00000001, 0x443c0314) +#define IOMUXC_PAD_SD2_DATA2_GPIO3_IO05 IOMUX_PADCFG(0x443c0164, 0x5, 0x00000000, 0x00000000, 0x443c0314) +#define IOMUXC_PAD_SD2_DATA2_CCMSRCGPCMIX_STOP IOMUX_PADCFG(0x443c0164, 0x6, 0x00000000, 0x00000000, 0x443c0314) +#define IOMUXC_PAD_SD2_DATA3_USDHC2_DATA3 IOMUX_PADCFG(0x443c0168, 0x0, 0x00000000, 0x00000000, 0x443c0318) +#define IOMUXC_PAD_SD2_DATA3_LPTMR2_ALT1 IOMUX_PADCFG(0x443c0168, 0x1, 0x443c0408, 0x00000001, 0x443c0318) +#define IOMUXC_PAD_SD2_DATA3_MQS2_LEFT IOMUX_PADCFG(0x443c0168, 0x2, 0x00000000, 0x00000000, 0x443c0318) +#define IOMUXC_PAD_SD2_DATA3_FLEXIO1_FLEXIO06 IOMUX_PADCFG(0x443c0168, 0x4, 0x443c0384, 0x00000001, 0x443c0318) +#define IOMUXC_PAD_SD2_DATA3_GPIO3_IO06 IOMUX_PADCFG(0x443c0168, 0x5, 0x00000000, 0x00000000, 0x443c0318) +#define IOMUXC_PAD_SD2_DATA3_CCMSRCGPCMIX_EARLY_RESET IOMUX_PADCFG(0x443c0168, 0x6, 0x00000000, 0x00000000, 0x443c0318) +#define IOMUXC_PAD_SD2_RESET_B_USDHC2_RESET_B IOMUX_PADCFG(0x443c016c, 0x0, 0x00000000, 0x00000000, 0x443c031c) +#define IOMUXC_PAD_SD2_RESET_B_LPTMR2_ALT2 IOMUX_PADCFG(0x443c016c, 0x1, 0x443c040c, 0x00000001, 0x443c031c) +#define IOMUXC_PAD_SD2_RESET_B_FLEXIO1_FLEXIO07 IOMUX_PADCFG(0x443c016c, 0x4, 0x443c0388, 0x00000001, 0x443c031c) +#define IOMUXC_PAD_SD2_RESET_B_GPIO3_IO07 IOMUX_PADCFG(0x443c016c, 0x5, 0x00000000, 0x00000000, 0x443c031c) +#define IOMUXC_PAD_SD2_RESET_B_CCMSRCGPCMIX_SYSTEM_RESET IOMUX_PADCFG(0x443c016c, 0x6, 0x00000000, 0x00000000, 0x443c031c) +#define IOMUXC_PAD_I2C1_SCL_LPI2C1_SCL IOMUX_PADCFG(0x443c0170, 0x0, 0x00000000, 0x00000000, 0x443c0320) +#define IOMUXC_PAD_I2C1_SCL_I3C1_SCL IOMUX_PADCFG(0x443c0170, 0x1, 0x00000000, 0x00000000, 0x443c0320) +#define IOMUXC_PAD_I2C1_SCL_LPUART1_DCB_B IOMUX_PADCFG(0x443c0170, 0x2, 0x00000000, 0x00000000, 0x443c0320) +#define IOMUXC_PAD_I2C1_SCL_TPM2_CH0 IOMUX_PADCFG(0x443c0170, 0x3, 0x00000000, 0x00000000, 0x443c0320) +#define IOMUXC_PAD_I2C1_SCL_GPIO1_IO00 IOMUX_PADCFG(0x443c0170, 0x5, 0x00000000, 0x00000000, 0x443c0320) +#define IOMUXC_PAD_I2C1_SDA_LPI2C1_SDA IOMUX_PADCFG(0x443c0174, 0x0, 0x00000000, 0x00000000, 0x443c0324) +#define IOMUXC_PAD_I2C1_SDA_I3C1_SDA IOMUX_PADCFG(0x443c0174, 0x1, 0x00000000, 0x00000000, 0x443c0324) +#define IOMUXC_PAD_I2C1_SDA_LPUART1_RIN_B IOMUX_PADCFG(0x443c0174, 0x2, 0x00000000, 0x00000000, 0x443c0324) +#define IOMUXC_PAD_I2C1_SDA_TPM2_CH1 IOMUX_PADCFG(0x443c0174, 0x3, 0x00000000, 0x00000000, 0x443c0324) +#define IOMUXC_PAD_I2C1_SDA_GPIO1_IO01 IOMUX_PADCFG(0x443c0174, 0x5, 0x00000000, 0x00000000, 0x443c0324) +#define IOMUXC_PAD_I2C2_SCL_LPI2C2_SCL IOMUX_PADCFG(0x443c0178, 0x0, 0x00000000, 0x00000000, 0x443c0328) +#define IOMUXC_PAD_I2C2_SCL_I3C1_PUR IOMUX_PADCFG(0x443c0178, 0x1, 0x00000000, 0x00000000, 0x443c0328) +#define IOMUXC_PAD_I2C2_SCL_LPUART2_DCB_B IOMUX_PADCFG(0x443c0178, 0x2, 0x00000000, 0x00000000, 0x443c0328) +#define IOMUXC_PAD_I2C2_SCL_TPM2_CH2 IOMUX_PADCFG(0x443c0178, 0x3, 0x00000000, 0x00000000, 0x443c0328) +#define IOMUXC_PAD_I2C2_SCL_SAI1_RX_SYNC IOMUX_PADCFG(0x443c0178, 0x4, 0x00000000, 0x00000000, 0x443c0328) +#define IOMUXC_PAD_I2C2_SCL_GPIO1_IO02 IOMUX_PADCFG(0x443c0178, 0x5, 0x00000000, 0x00000000, 0x443c0328) +#define IOMUXC_PAD_I2C2_SCL_I3C1_PUR_B IOMUX_PADCFG(0x443c0178, 0x6, 0x00000000, 0x00000000, 0x443c0328) +#define IOMUXC_PAD_I2C2_SDA_LPI2C2_SDA IOMUX_PADCFG(0x443c017c, 0x0, 0x00000000, 0x00000000, 0x443c032c) +#define IOMUXC_PAD_I2C2_SDA_LPUART2_RIN_B IOMUX_PADCFG(0x443c017c, 0x2, 0x00000000, 0x00000000, 0x443c032c) +#define IOMUXC_PAD_I2C2_SDA_TPM2_CH3 IOMUX_PADCFG(0x443c017c, 0x3, 0x00000000, 0x00000000, 0x443c032c) +#define IOMUXC_PAD_I2C2_SDA_SAI1_RX_BCLK IOMUX_PADCFG(0x443c017c, 0x4, 0x00000000, 0x00000000, 0x443c032c) +#define IOMUXC_PAD_I2C2_SDA_GPIO1_IO03 IOMUX_PADCFG(0x443c017c, 0x5, 0x00000000, 0x00000000, 0x443c032c) +#define IOMUXC_PAD_UART1_RXD_LPUART1_RX IOMUX_PADCFG(0x443c0180, 0x0, 0x00000000, 0x00000000, 0x443c0330) +#define IOMUXC_PAD_UART1_RXD_S400_UART_RX IOMUX_PADCFG(0x443c0180, 0x1, 0x00000000, 0x00000000, 0x443c0330) +#define IOMUXC_PAD_UART1_RXD_LPSPI2_SIN IOMUX_PADCFG(0x443c0180, 0x2, 0x00000000, 0x00000000, 0x443c0330) +#define IOMUXC_PAD_UART1_RXD_TPM1_CH0 IOMUX_PADCFG(0x443c0180, 0x3, 0x00000000, 0x00000000, 0x443c0330) +#define IOMUXC_PAD_UART1_RXD_GPIO1_IO04 IOMUX_PADCFG(0x443c0180, 0x5, 0x00000000, 0x00000000, 0x443c0330) +#define IOMUXC_PAD_UART1_TXD_LPUART1_TX IOMUX_PADCFG(0x443c0184, 0x0, 0x00000000, 0x00000000, 0x443c0334) +#define IOMUXC_PAD_UART1_TXD_S400_UART_TX IOMUX_PADCFG(0x443c0184, 0x1, 0x00000000, 0x00000000, 0x443c0334) +#define IOMUXC_PAD_UART1_TXD_LPSPI2_PCS0 IOMUX_PADCFG(0x443c0184, 0x2, 0x00000000, 0x00000000, 0x443c0334) +#define IOMUXC_PAD_UART1_TXD_TPM1_CH1 IOMUX_PADCFG(0x443c0184, 0x3, 0x00000000, 0x00000000, 0x443c0334) +#define IOMUXC_PAD_UART1_TXD_GPIO1_IO05 IOMUX_PADCFG(0x443c0184, 0x5, 0x00000000, 0x00000000, 0x443c0334) +#define IOMUXC_PAD_UART2_RXD_LPUART2_RX IOMUX_PADCFG(0x443c0188, 0x0, 0x00000000, 0x00000000, 0x443c0338) +#define IOMUXC_PAD_UART2_RXD_LPUART1_CTS_B IOMUX_PADCFG(0x443c0188, 0x1, 0x00000000, 0x00000000, 0x443c0338) +#define IOMUXC_PAD_UART2_RXD_LPSPI2_SOUT IOMUX_PADCFG(0x443c0188, 0x2, 0x00000000, 0x00000000, 0x443c0338) +#define IOMUXC_PAD_UART2_RXD_TPM1_CH2 IOMUX_PADCFG(0x443c0188, 0x3, 0x00000000, 0x00000000, 0x443c0338) +#define IOMUXC_PAD_UART2_RXD_SAI1_MCLK IOMUX_PADCFG(0x443c0188, 0x4, 0x443c0448, 0x00000000, 0x443c0338) +#define IOMUXC_PAD_UART2_RXD_GPIO1_IO06 IOMUX_PADCFG(0x443c0188, 0x5, 0x00000000, 0x00000000, 0x443c0338) +#define IOMUXC_PAD_UART2_TXD_LPUART2_TX IOMUX_PADCFG(0x443c018c, 0x0, 0x00000000, 0x00000000, 0x443c033c) +#define IOMUXC_PAD_UART2_TXD_LPUART1_RTS_B IOMUX_PADCFG(0x443c018c, 0x1, 0x00000000, 0x00000000, 0x443c033c) +#define IOMUXC_PAD_UART2_TXD_LPSPI2_SCK IOMUX_PADCFG(0x443c018c, 0x2, 0x00000000, 0x00000000, 0x443c033c) +#define IOMUXC_PAD_UART2_TXD_TPM1_CH3 IOMUX_PADCFG(0x443c018c, 0x3, 0x00000000, 0x00000000, 0x443c033c) +#define IOMUXC_PAD_UART2_TXD_GPIO1_IO07 IOMUX_PADCFG(0x443c018c, 0x5, 0x00000000, 0x00000000, 0x443c033c) +#define IOMUXC_PAD_PDM_CLK_PDM_CLK IOMUX_PADCFG(0x443c0190, 0x0, 0x00000000, 0x00000000, 0x443c0340) +#define IOMUXC_PAD_PDM_CLK_MQS1_LEFT IOMUX_PADCFG(0x443c0190, 0x1, 0x00000000, 0x00000000, 0x443c0340) +#define IOMUXC_PAD_PDM_CLK_LPTMR1_ALT1 IOMUX_PADCFG(0x443c0190, 0x4, 0x00000000, 0x00000000, 0x443c0340) +#define IOMUXC_PAD_PDM_CLK_GPIO1_IO08 IOMUX_PADCFG(0x443c0190, 0x5, 0x00000000, 0x00000000, 0x443c0340) +#define IOMUXC_PAD_PDM_CLK_CAN1_TX IOMUX_PADCFG(0x443c0190, 0x6, 0x00000000, 0x00000000, 0x443c0340) +#define IOMUXC_PAD_PDM_BIT_STREAM0_PDM_BIT_STREAM00 IOMUX_PADCFG(0x443c0194, 0x0, 0x443c0438, 0x00000002, 0x443c0344) +#define IOMUXC_PAD_PDM_BIT_STREAM0_MQS1_RIGHT IOMUX_PADCFG(0x443c0194, 0x1, 0x00000000, 0x00000000, 0x443c0344) +#define IOMUXC_PAD_PDM_BIT_STREAM0_LPSPI1_PCS1 IOMUX_PADCFG(0x443c0194, 0x2, 0x00000000, 0x00000000, 0x443c0344) +#define IOMUXC_PAD_PDM_BIT_STREAM0_TPM1_EXTCLK IOMUX_PADCFG(0x443c0194, 0x3, 0x00000000, 0x00000000, 0x443c0344) +#define IOMUXC_PAD_PDM_BIT_STREAM0_LPTMR1_ALT2 IOMUX_PADCFG(0x443c0194, 0x4, 0x00000000, 0x00000000, 0x443c0344) +#define IOMUXC_PAD_PDM_BIT_STREAM0_GPIO1_IO09 IOMUX_PADCFG(0x443c0194, 0x5, 0x00000000, 0x00000000, 0x443c0344) +#define IOMUXC_PAD_PDM_BIT_STREAM0_CAN1_RX IOMUX_PADCFG(0x443c0194, 0x6, 0x443c0360, 0x00000000, 0x443c0344) +#define IOMUXC_PAD_PDM_BIT_STREAM1_PDM_BIT_STREAM01 IOMUX_PADCFG(0x443c0198, 0x0, 0x443c043c, 0x00000002, 0x443c0348) +#define IOMUXC_PAD_PDM_BIT_STREAM1_NMI_GLUE_NMI IOMUX_PADCFG(0x443c0198, 0x1, 0x00000000, 0x00000000, 0x443c0348) +#define IOMUXC_PAD_PDM_BIT_STREAM1_LPSPI2_PCS1 IOMUX_PADCFG(0x443c0198, 0x2, 0x00000000, 0x00000000, 0x443c0348) +#define IOMUXC_PAD_PDM_BIT_STREAM1_TPM2_EXTCLK IOMUX_PADCFG(0x443c0198, 0x3, 0x00000000, 0x00000000, 0x443c0348) +#define IOMUXC_PAD_PDM_BIT_STREAM1_LPTMR1_ALT3 IOMUX_PADCFG(0x443c0198, 0x4, 0x00000000, 0x00000000, 0x443c0348) +#define IOMUXC_PAD_PDM_BIT_STREAM1_GPIO1_IO10 IOMUX_PADCFG(0x443c0198, 0x5, 0x00000000, 0x00000000, 0x443c0348) +#define IOMUXC_PAD_PDM_BIT_STREAM1_CCMSRCGPCMIX_EXT_CLK1 IOMUX_PADCFG(0x443c0198, 0x6, 0x443c0368, 0x00000001, 0x443c0348) +#define IOMUXC_PAD_SAI1_TXFS_SAI1_TX_SYNC IOMUX_PADCFG(0x443c019c, 0x0, 0x00000000, 0x00000000, 0x443c034c) +#define IOMUXC_PAD_SAI1_TXFS_SAI1_TX_DATA01 IOMUX_PADCFG(0x443c019c, 0x1, 0x00000000, 0x00000000, 0x443c034c) +#define IOMUXC_PAD_SAI1_TXFS_LPSPI1_PCS0 IOMUX_PADCFG(0x443c019c, 0x2, 0x00000000, 0x00000000, 0x443c034c) +#define IOMUXC_PAD_SAI1_TXFS_LPUART2_DTR_B IOMUX_PADCFG(0x443c019c, 0x3, 0x00000000, 0x00000000, 0x443c034c) +#define IOMUXC_PAD_SAI1_TXFS_MQS1_LEFT IOMUX_PADCFG(0x443c019c, 0x4, 0x00000000, 0x00000000, 0x443c034c) +#define IOMUXC_PAD_SAI1_TXFS_GPIO1_IO11 IOMUX_PADCFG(0x443c019c, 0x5, 0x00000000, 0x00000000, 0x443c034c) +#define IOMUXC_PAD_SAI1_TXC_SAI1_TX_BCLK IOMUX_PADCFG(0x443c01a0, 0x0, 0x00000000, 0x00000000, 0x443c0350) +#define IOMUXC_PAD_SAI1_TXC_LPUART2_CTS_B IOMUX_PADCFG(0x443c01a0, 0x1, 0x00000000, 0x00000000, 0x443c0350) +#define IOMUXC_PAD_SAI1_TXC_LPSPI1_SIN IOMUX_PADCFG(0x443c01a0, 0x2, 0x00000000, 0x00000000, 0x443c0350) +#define IOMUXC_PAD_SAI1_TXC_LPUART1_DSR_B IOMUX_PADCFG(0x443c01a0, 0x3, 0x00000000, 0x00000000, 0x443c0350) +#define IOMUXC_PAD_SAI1_TXC_CAN1_RX IOMUX_PADCFG(0x443c01a0, 0x4, 0x443c0360, 0x00000001, 0x443c0350) +#define IOMUXC_PAD_SAI1_TXC_GPIO1_IO12 IOMUX_PADCFG(0x443c01a0, 0x5, 0x00000000, 0x00000000, 0x443c0350) +#define IOMUXC_PAD_SAI1_TXD0_SAI1_TX_DATA00 IOMUX_PADCFG(0x443c01a4, 0x0, 0x00000000, 0x00000000, 0x443c0354) +#define IOMUXC_PAD_SAI1_TXD0_LPUART2_RTS_B IOMUX_PADCFG(0x443c01a4, 0x1, 0x00000000, 0x00000000, 0x443c0354) +#define IOMUXC_PAD_SAI1_TXD0_LPSPI1_SCK IOMUX_PADCFG(0x443c01a4, 0x2, 0x00000000, 0x00000000, 0x443c0354) +#define IOMUXC_PAD_SAI1_TXD0_LPUART1_DTR_B IOMUX_PADCFG(0x443c01a4, 0x3, 0x00000000, 0x00000000, 0x443c0354) +#define IOMUXC_PAD_SAI1_TXD0_CAN1_TX IOMUX_PADCFG(0x443c01a4, 0x4, 0x00000000, 0x00000000, 0x443c0354) +#define IOMUXC_PAD_SAI1_TXD0_GPIO1_IO13 IOMUX_PADCFG(0x443c01a4, 0x5, 0x00000000, 0x00000000, 0x443c0354) +#define IOMUXC_PAD_SAI1_RXD0_SAI1_RX_DATA00 IOMUX_PADCFG(0x443c01a8, 0x0, 0x00000000, 0x00000000, 0x443c0358) +#define IOMUXC_PAD_SAI1_RXD0_SAI1_MCLK IOMUX_PADCFG(0x443c01a8, 0x1, 0x443c0448, 0x00000001, 0x443c0358) +#define IOMUXC_PAD_SAI1_RXD0_LPSPI1_SOUT IOMUX_PADCFG(0x443c01a8, 0x2, 0x00000000, 0x00000000, 0x443c0358) +#define IOMUXC_PAD_SAI1_RXD0_LPUART2_DSR_B IOMUX_PADCFG(0x443c01a8, 0x3, 0x00000000, 0x00000000, 0x443c0358) +#define IOMUXC_PAD_SAI1_RXD0_MQS1_RIGHT IOMUX_PADCFG(0x443c01a8, 0x4, 0x00000000, 0x00000000, 0x443c0358) +#define IOMUXC_PAD_SAI1_RXD0_GPIO1_IO14 IOMUX_PADCFG(0x443c01a8, 0x5, 0x00000000, 0x00000000, 0x443c0358) +#define IOMUXC_PAD_WDOG_ANY_WDOG1_WDOG_ANY IOMUX_PADCFG(0x443c01ac, 0x0, 0x00000000, 0x00000000, 0x443c035c) +#define IOMUXC_PAD_WDOG_ANY_GPIO1_IO15 IOMUX_PADCFG(0x443c01ac, 0x5, 0x00000000, 0x00000000, 0x443c035c) + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_PINMUX_H */ diff --git a/arch/arm64/src/imx9/hardware/imx93/imx93_pll.h b/arch/arm64/src/imx9/hardware/imx93/imx93_pll.h new file mode 100644 index 0000000000000..fa99b92c7f893 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx93/imx93_pll.h @@ -0,0 +1,226 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx93/imx93_pll.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_PLL_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_PLL_H + +/* All registers besides STATUS have SET, CLR, TGL and VAL shadow registers */ + +#define PLL_REG_VAL_OFFSET (0x00) +#define PLL_REG_SET_OFFSET (0x04) +#define PLL_REG_CLR_OFFSET (0x08) +#define PLL_REG_TGL_OFFSET (0x0c) + +/* User can access the individual registers via these macros */ + +#define PLL_VAL(n) ((n) + PLL_REG_VAL_OFFSET) /* Same as the register itself */ +#define PLL_SET(n) ((n) + PLL_REG_SET_OFFSET) +#define PLL_CLR(n) ((n) + PLL_REG_CLR_OFFSET) +#define PLL_TGL(n) ((n) + PLL_REG_TGL_OFFSET) + +/* Common offsets for all PLL registers, existence depends on the register + * itself + */ + +#define PLL_CTRL_OFFSET (0x00) /* PLL Control */ +#define PLL_SPREAD_SPECTRUM_OFFSET (0x30) /* Spread Spectrum */ +#define PLL_NUMERATOR_OFFSET (0x40) /* Numerator */ +#define PLL_DENOMINATOR_OFFSET (0x50) /* Denominator */ +#define PLL_DIV_OFFSET (0x60) /* PLL Dividers */ +#define PLL_DFS_CTRL_0_OFFSET (0x70) /* DFS Control */ +#define PLL_DFS_DIV_0_OFFSET (0x80) /* DFS Division_0 */ +#define PLL_DFS_CTRL_1_OFFSET (0x90) /* DFS Control */ +#define PLL_DFS_DIV_1_OFFSET (0xa0) /* DFS Division_1 */ +#define PLL_DFS_CTRL_2_OFFSET (0xb0) /* DFS Control */ +#define PLL_DFS_DIV_2_OFFSET (0xc0) /* DFS Division_2 */ +#define PLL_PLL_STATUS_OFFSET (0xf0) /* PLL Status */ +#define PLL_DFS_STATUS_OFFSET (0xf4) /* DFS Status */ + +/* Register addresses */ + +#define PLL_CTRL(n) ((n) + PLL_CTRL_OFFSET) +#define PLL_SPREAD_SPECTRUM(n) ((n) + PLL_SPREAD_SPECTRUM_OFFSET) +#define PLL_NUMERATOR(n) ((n) + PLL_NUMERATOR_OFFSET) +#define PLL_DENOMINATOR(n) ((n) + PLL_DENOMINATOR_OFFSET) +#define PLL_DIV(n) ((n) + PLL_DIV_OFFSET) +#define PLL_DFS_CTRL_0(n) ((n) + PLL_DFS_CTRL_0_OFFSET) +#define PLL_DFS_DIV_0(n) ((n) + PLL_DFS_DIV_0_OFFSET) +#define PLL_DFS_CTRL_1(n) ((n) + PLL_DFS_CTRL_1_OFFSET) +#define PLL_DFS_DIV_1(n) ((n) + PLL_DFS_DIV_1_OFFSET) +#define PLL_DFS_CTRL_2(n) ((n) + PLL_DFS_CTRL_2_OFFSET) +#define PLL_DFS_DIV_2(n) ((n) + PLL_DFS_DIV_2_OFFSET) +#define PLL_PLL_STATUS(n) ((n) + PLL_PLL_STATUS_OFFSET) +#define PLL_DFS_STATUS(n) ((n) + PLL_DFS_STATUS_OFFSET) + +/* SYSPLL registers */ + +#define SYSPLL_CTRL (IMX9_SYSPLL_BASE + PLL_CTRL_OFFSET) +#define SYSPLL_SPREAD_SPECTRUM (IMX9_SYSPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET) +#define SYSPLL_NUMERATOR (IMX9_SYSPLL_BASE + PLL_NUMERATOR_OFFSET) +#define SYSPLL_DENOMINATOR (IMX9_SYSPLL_BASE + PLL_DENOMINATOR_OFFSET) +#define SYSPLL_DIV (IMX9_SYSPLL_BASE + PLL_DIV_OFFSET) +#define SYSPLL_DFS_CTRL_0 (IMX9_SYSPLL_BASE + PLL_DFS_CTRL_0_OFFSET) +#define SYSPLL_DFS_DIV_0 (IMX9_SYSPLL_BASE + PLL_DFS_DIV_0_OFFSET) +#define SYSPLL_DFS_CTRL_1 (IMX9_SYSPLL_BASE + PLL_DFS_CTRL_1_OFFSET) +#define SYSPLL_DFS_DIV_1 (IMX9_SYSPLL_BASE + PLL_DFS_DIV_1_OFFSET) +#define SYSPLL_DFS_CTRL_2 (IMX9_SYSPLL_BASE + PLL_DFS_CTRL_2_OFFSET) +#define SYSPLL_DFS_DIV_2 (IMX9_SYSPLL_BASE + PLL_DFS_DIV_2_OFFSET) +#define SYSPLL_PLL_STATUS (IMX9_SYSPLL_BASE + PLL_PLL_STATUS_OFFSET) +#define SYSPLL_DFS_STATUS (IMX9_SYSPLL_BASE + PLL_DFS_STATUS_OFFSET) + +/* ARMPLL registers */ + +#define ARMPLL_CTRL (IMX9_ARMPLL_BASE + PLL_CTRL_OFFSET) +#define ARMPLL_DIV (IMX9_ARMPLL_BASE + PLL_DIV_OFFSET) +#define ARMPLL_PLL_STATUS (IMX9_ARMPLL_BASE + PLL_PLL_STATUS_OFFSET) + +/* AUDIOPLL registers */ + +#define AUDIOPLL_CTRL (IMX9_AUDIOPLL_BASE + PLL_CTRL_OFFSET) +#define AUDIOPLL_SPREAD_SPECTRUM (IMX9_AUDIOPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET) +#define AUDIOPLL_NUMERATOR (IMX9_AUDIOPLL_BASE + PLL_NUMERATOR_OFFSET) +#define AUDIOPLL_DENOMINATOR (IMX9_AUDIOPLL_BASE + PLL_DENOMINATOR_OFFSET) +#define AUDIOPLL_DIV (IMX9_AUDIOPLL_BASE + PLL_DIV_OFFSET) +#define AUDIOPLL_PLL_STATUS (IMX9_AUDIOPLL_BASE + PLL_PLL_STATUS_OFFSET) + +/* DRAMPLL registers */ + +#define DRAMPLL_CTRL (IMX9_AUDIOPLL_BASE + PLL_CTRL_OFFSET) +#define DRAMPLL_SPREAD_SPECTRUM (IMX9_AUDIOPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET) +#define DRAMPLL_NUMERATOR (IMX9_AUDIOPLL_BASE + PLL_NUMERATOR_OFFSET) +#define DRAMPLL_DENOMINATOR (IMX9_AUDIOPLL_BASE + PLL_DENOMINATOR_OFFSET) +#define DRAMPLL_DIV (IMX9_AUDIOPLL_BASE + PLL_DIV_OFFSET) +#define DRAMPLL_PLL_STATUS (IMX9_AUDIOPLL_BASE + PLL_PLL_STATUS_OFFSET) + +/* VIDEOPLL registers */ + +#define VIDEOPLL_CTRL (IMX9_VIDEOPLL_BASE + PLL_CTRL_OFFSET) +#define VIDEOPLL_SPREAD_SPECTRUM (IMX9_VIDEOPLL_BASE + PLL_SPREAD_SPECTRUM_OFFSET) +#define VIDEOPLL_NUMERATOR (IMX9_VIDEOPLL_BASE + PLL_NUMERATOR_OFFSET) +#define VIDEOPLL_DENOMINATOR (IMX9_VIDEOPLL_BASE + PLL_DENOMINATOR_OFFSET) +#define VIDEOPLL_DIV (IMX9_VIDEOPLL_BASE + PLL_DIV_OFFSET) +#define VIDEOPLL_PLL_STATUS (IMX9_VIDEOPLL_BASE + PLL_PLL_STATUS_OFFSET) + +/* PLL Control (CTRL) */ + +#define PLL_CTRL_POWERUP (1 << 0) /* Bit 0: Power up PLL */ +#define PLL_CTRL_CLKMUX_EN (1 << 1) /* Bit 1: Enable CLKMUX output */ +#define PLL_CTRL_CLKMUX_BYPASS (1 << 2) /* Bit 2: Enable CLKMUX bypass */ +#define PLL_CTRL_SPREADCTL (1 << 8) /* Bit 8: Modulation Type Select */ +#define PLL_CTRL_HW_CTRL_SEL (1 << 16) /* Bit 16: Hardware Control Select */ +#define PLL_CTRL_LOCK_BYPASS (1 << 31) /* Bit 31: Lock bypass */ + +/* Spread Spectrum (SPREAD_SPECTRUM) */ + +#define PLL_SPREAD_SPECTRUM_STEP_SHIFT (0) /* Bits 14-0: Set spread spectrum step */ +#define PLL_SPREAD_SPECTRUM_STEP_MASK (0x7fff << PLL_SPREAD_SPECTRUM_STEP_SHIFT) +#define PLL_SPREAD_SPECTRUM_STEP(n) (((n) << PLL_SPREAD_SPECTRUM_STEP_SHIFT) & PLL_SPREAD_SPECTRUM_STEP_MASK) +#define PLL_SPREAD_SPECTRUM_ENABLE (1 << 15) /* Bit 15: Enable spread spectrum */ +#define PLL_SPREAD_SPECTRUM_STOP_SHIFT (16) /* Bits 16-31: Set spread spectrum stop */ +#define PLL_SPREAD_SPECTRUM_STOP_MASK (0xffff << PLL_SPREAD_SPECTRUM_STOP_SHIFT) +#define PLL_SPREAD_SPECTRUM_STOP(n) (((n) << PLL_SPREAD_SPECTRUM_STOP_SHIFT) & PLL_SPREAD_SPECTRUM_STOP_MASK) + +/* Numerator (NUMERATOR) */ + +#define PLL_NUMERATOR_MFN_SHIFT (2) /* Bits 2-31: Numerator MFN value */ +#define PLL_NUMERATOR_MFN_MASK (0x3fffffff << PLL_NUMERATOR_MFN_SHIFT) +#define PLL_NUMERATOR_MFN(n) (((n) << PLL_NUMERATOR_MFN_SHIFT) & PLL_NUMERATOR_MFN_MASK) + +/* Denominator (DENOMINATOR) */ + +#define PLL_DENOMINATOR_MFD_SHIFT (0) /* Bits 0-29: Denominator MFD value */ +#define PLL_DENOMINATOR_MFD_MASK (0x3fffffff << PLL_DENOMINATOR_MFD_SHIFT) +#define PLL_DENOMINATOR_MFD(n) (((n) << PLL_DENOMINATOR_MFD_SHIFT) & PLL_DENOMINATOR_MFD_MASK) + +/* PLL Dividers (DIV) */ + +#define PLL_DIV_ODIV_SHIFT (0) /* Bits 0-7: Output Frequency Divider for Clock Output */ +#define PLL_DIV_ODIV_MASK (0xff << PLL_DIV_ODIV_SHIFT) +#define PLL_DIV_ODIV(n) (((n) << PLL_DIV_ODIV_SHIFT) & PLL_DIV_ODIV_MASK) +#define PLL_DIV_RDIV_SHIFT (13) /* Bits 13-15: Input Clock Predivider */ +#define PLL_DIV_RDIV_MASK (0xe << PLL_DIV_RDIV_SHIFT) +#define PLL_DIV_RDIV(n) (((n) << PLL_DIV_RDIV_SHIFT) & PLL_DIV_RDIV_MASK) +#define PLL_DIV_MFI_SHIFT (16) /* Bits 16-24: Integer Portion of Loop Divider */ +#define PLL_DIV_MFI_MASK (0x1ff << PLL_DIV_MFI_SHIFT) +#define PLL_DIV_MFI(n) (((n) << PLL_DIV_MFI_SHIFT) & PLL_DIV_MFI_MASK) + +/* DFS Control (DFS_CTRL_0 - DFS_CTRL_2) */ + +#define PLL_DFS_HW_CTRL_SEL (1 << 16) /* Bit 16: Hardware Control Select */ +#define PLL_DFS_BYPASS_EN (1 << 23) /* Bit 23: Bypass Enable */ +#define PLL_DFS_CLKOUT_DIVBY2_EN (1 << 29) /* Bit 29: DFS Clock Output Divide by 2 Enable */ +#define PLL_DFS_CLKOUT_EN (1 << 30) /* Bit 30: DFS Clock Output Enable */ +#define PLL_DFS_ENABLE (1 << 31) /* Bit 31: DFS Block Enable */ + +/* DFS Division_a (DFS_DIV_0 - DFS_DIV_2) */ + +#define PLL_DFS_MFN_SHIFT (0) /* Bits 0-2: MFN */ +#define PLL_DFS_MFN_MASK (0x7 << PLL_DFS_MFN_SHIFT) +#define PLL_DFS_MFN(n) (((n) << PLL_DFS_MFN_SHIFT) & PLL_DFS_MFN_MASK) +#define PLL_DFS_MFI_SHIFT (8) /* Bits 8-15: MFI */ +#define PLL_DFS_MFI_MASK (0xFF << PLL_DFS_MFI_SHIFT) +#define PLL_DFS_MFI(n) (((n) << PLL_DFS_MFI_SHIFT) & PLL_DFS_MFI_MASK) + +/* PLL Dividers (DIV) */ + +#define PLL_PLL_STATUS_PLL_LOCK (1 << 0) /* Bit 0: PLL is locked */ +#define PLL_PLL_STATUS_PLL_LOL (1 << 1) /* Bit 1: PLL lock is lost */ +#define PLL_PLL_STATUS_ANA_MFN_SHIFT (2) +#define PLL_PLL_STATUS_ANA_MFN_MASK (0x3fffffff << PLL_PLL_STATUS_ANA_MFN_SHIFT) +#define PLL_PLL_STATUS_ANA_MFN(n) (((n) << PLL_PLL_STATUS_ANA_MFN_SHIFT) & PLL_PLL_STATUS_ANA_MFN_MASK) + +/* DFS Status (DFS_STATUS) */ + +#define PLL_DFS_STATUS_DFS_OK_SHIFT (0) /* Bits 0-2: DFS OK status */ +#define PLL_DFS_STATUS_DFS_OK_MASK (0x7 << PLL_DFS_STATUS_DFS_OK_SHIFT) +#define PLL_DFS_STATUS_DFS_OK(n) (((n) << PLL_DFS_STATUS_DFS_OK_SHIFT) & PLL_DFS_STATUS_DFS_OK_MASK) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct pll_parms +{ + /* Integer part (DIV) */ + + struct + { + uint32_t rdiv; /* Input clock divider */ + uint32_t odiv; /* PLL output divider */ + uint32_t mfi; /* PLL integer divider */ + }; + + /* Fractional part (NUMERATOR / DENOMINATOR) */ + + struct + { + uint32_t mfn; /* PLL fractional divider numerator */ + uint32_t mfd; /* PLL fractional divider denominator */ + }; +}; + +struct pfd_parms +{ + uint32_t mfi; /* PLL integer divider */ + uint32_t mfn; /* PLL fractional divider numerator */ + bool divby2_en; /* Enable the divide-by-2 output */ +}; + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX93_IMX93_PLL_H_*/ diff --git a/arch/arm64/src/imx9/hardware/imx9_ccm.h b/arch/arm64/src/imx9/hardware/imx9_ccm.h new file mode 100644 index 0000000000000..f4a68a0a31514 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_ccm.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_ccm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_CCM_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_CCM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/imx9_memorymap.h" + +#if defined(CONFIG_ARCH_CHIP_IMX93) +# include "hardware/imx93/imx93_ccm.h" +# include "hardware/imx93/imx93_pll.h" +#else +# error Unrecognized i.MX9 architecture +#endif + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_CCM_H_ */ diff --git a/arch/arm64/src/imx9/hardware/imx9_flexio.h b/arch/arm64/src/imx9/hardware/imx9_flexio.h new file mode 100644 index 0000000000000..2d1c9cabe5410 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_flexio.h @@ -0,0 +1,823 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_flexio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_FLEXIO_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_FLEXIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/imx9_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMX9_FLEXIO_VERID_OFFSET 0x0000 /* Version ID Register, offset: 0x0 */ +#define IMX9_FLEXIO_PARAM_OFFSET 0x0004 /* Parameter Register, offset: 0x4 */ +#define IMX9_FLEXIO_CTRL_OFFSET 0x0008 /* FlexIO Control Register, offset: 0x8 */ +#define IMX9_FLEXIO_PIN_OFFSET 0x000c /* Pin State Register, offset: 0xC */ +#define IMX9_FLEXIO_SHIFTSTAT_OFFSET 0x0010 /* Shifter Status Register, offset: 0x10 */ +#define IMX9_FLEXIO_SHIFTERR_OFFSET 0x0014 /* Shifter Error Register, offset: 0x14 */ +#define IMX9_FLEXIO_TIMSTAT_OFFSET 0x0018 /* Timer Status Register, offset: 0x18 */ +#define IMX9_FLEXIO_SHIFTSIEN_OFFSET 0x0020 /* Shifter Status Interrupt Enable, offset: 0x20 */ +#define IMX9_FLEXIO_SHIFTEIEN_OFFSET 0x0024 /* Shifter Error Interrupt Enable, offset: 0x24 */ +#define IMX9_FLEXIO_TIMIEN_OFFSET 0x0028 /* Timer Interrupt Enable Register, offset: 0x28 */ +#define IMX9_FLEXIO_SHIFTSDEN_OFFSET 0x0030 /* Shifter Status DMA Enable, offset: 0x30 */ +#define IMX9_FLEXIO_SHIFTSTATE_OFFSET 0x0040 /* Shifter State Register, offset: 0x40 */ +#define IMX9_FLEXIO_TRGSTAT_OFFSET 0x0048 /* Trigger Status */ +#define IMX9_FLEXIO_TRIGIEN_OFFSET 0x004c /* External Trigger Interrupt Enable */ +#define IMX9_FLEXIO_PINSTAT_OFFSET 0x0050 /* Pin Status */ +#define IMX9_FLEXIO_PINIEN_OFFSET 0x0054 /* Pin Interrupt Enable */ +#define IMX9_FLEXIO_PINREN_OFFSET 0x0058 /* Pin Rising Edge Enable */ +#define IMX9_FLEXIO_PINFEN_OFFSET 0x005c /* Pin Falling Edge Enable */ +#define IMX9_FLEXIO_PINOUTD_OFFSET 0x0060 /* Pin Output Data */ +#define IMX9_FLEXIO_PINOUTE_OFFSET 0x0064 /* Pin Output Enable */ +#define IMX9_FLEXIO_PINOUTDIS_OFFSET 0x0068 /* Pin Output Disable */ +#define IMX9_FLEXIO_PINOUTCLR_OFFSET 0x006c /* Pin Output Clear */ +#define IMX9_FLEXIO_PINOUTSET_OFFSET 0x0070 /* Pin Output Set */ +#define IMX9_FLEXIO_PINOUTTOG_OFFSET 0x0074 /* Pin Output Toggle */ +#define IMX9_FLEXIO_SHIFTCTL0_OFFSET 0x0080 /* Shifter Control N Register, array offset: 0x80, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTCTL1_OFFSET 0x0084 +#define IMX9_FLEXIO_SHIFTCTL2_OFFSET 0x0088 +#define IMX9_FLEXIO_SHIFTCTL3_OFFSET 0x008c +#define IMX9_FLEXIO_SHIFTCTL4_OFFSET 0x0090 +#define IMX9_FLEXIO_SHIFTCTL5_OFFSET 0x0094 +#define IMX9_FLEXIO_SHIFTCTL6_OFFSET 0x0098 +#define IMX9_FLEXIO_SHIFTCTL7_OFFSET 0x009c +#define IMX9_FLEXIO_SHIFTCFG0_OFFSET 0x0100 /* Shifter Configuration N Register, array offset: 0x100, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTCFG1_OFFSET 0x0104 +#define IMX9_FLEXIO_SHIFTCFG2_OFFSET 0x0108 +#define IMX9_FLEXIO_SHIFTCFG3_OFFSET 0x010c +#define IMX9_FLEXIO_SHIFTCFG4_OFFSET 0x0110 +#define IMX9_FLEXIO_SHIFTCFG5_OFFSET 0x0114 +#define IMX9_FLEXIO_SHIFTCFG6_OFFSET 0x0118 +#define IMX9_FLEXIO_SHIFTCFG7_OFFSET 0x011c +#define IMX9_FLEXIO_SHIFTBUF0_OFFSET 0x0200 /* Shifter Buffer N Register, array offset: 0x200, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUF1_OFFSET 0x0204 +#define IMX9_FLEXIO_SHIFTBUF2_OFFSET 0x0208 +#define IMX9_FLEXIO_SHIFTBUF3_OFFSET 0x020c +#define IMX9_FLEXIO_SHIFTBUF4_OFFSET 0x0210 +#define IMX9_FLEXIO_SHIFTBUF5_OFFSET 0x0214 +#define IMX9_FLEXIO_SHIFTBUF6_OFFSET 0x0218 +#define IMX9_FLEXIO_SHIFTBUF7_OFFSET 0x021c +#define IMX9_FLEXIO_SHIFTBUFBIS0_OFFSET 0x0280 /* Shifter Buffer N Bit Swapped Register, array offset: 0x280, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFBIS1_OFFSET 0x0284 +#define IMX9_FLEXIO_SHIFTBUFBIS2_OFFSET 0x0288 +#define IMX9_FLEXIO_SHIFTBUFBIS3_OFFSET 0x028c +#define IMX9_FLEXIO_SHIFTBUFBIS4_OFFSET 0x0290 +#define IMX9_FLEXIO_SHIFTBUFBIS5_OFFSET 0x0294 +#define IMX9_FLEXIO_SHIFTBUFBIS6_OFFSET 0x0298 +#define IMX9_FLEXIO_SHIFTBUFBIS7_OFFSET 0x029c +#define IMX9_FLEXIO_SHIFTBUFBYS0_OFFSET 0x0300 /* Shifter Buffer N Byte Swapped Register, array offset: 0x300, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFBYS1_OFFSET 0x0304 +#define IMX9_FLEXIO_SHIFTBUFBYS2_OFFSET 0x0308 +#define IMX9_FLEXIO_SHIFTBUFBYS3_OFFSET 0x030c +#define IMX9_FLEXIO_SHIFTBUFBYS4_OFFSET 0x0310 +#define IMX9_FLEXIO_SHIFTBUFBYS5_OFFSET 0x0314 +#define IMX9_FLEXIO_SHIFTBUFBYS6_OFFSET 0x0318 +#define IMX9_FLEXIO_SHIFTBUFBYS7_OFFSET 0x031c +#define IMX9_FLEXIO_SHIFTBUFBBS0_OFFSET 0x0380 /* Shifter Buffer N Bit Byte Swapped Register, array offset: 0x380, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFBBS1_OFFSET 0x0384 +#define IMX9_FLEXIO_SHIFTBUFBBS2_OFFSET 0x0388 +#define IMX9_FLEXIO_SHIFTBUFBBS3_OFFSET 0x038c +#define IMX9_FLEXIO_SHIFTBUFBBS4_OFFSET 0x0390 +#define IMX9_FLEXIO_SHIFTBUFBBS5_OFFSET 0x0394 +#define IMX9_FLEXIO_SHIFTBUFBBS6_OFFSET 0x0398 +#define IMX9_FLEXIO_SHIFTBUFBBS7_OFFSET 0x039c +#define IMX9_FLEXIO_TIMCTL0_OFFSET 0x0400 /* Timer Control N Register, array offset: 0x400, array step: 0x4 */ +#define IMX9_FLEXIO_TIMCTL1_OFFSET 0x0404 +#define IMX9_FLEXIO_TIMCTL2_OFFSET 0x0408 +#define IMX9_FLEXIO_TIMCTL3_OFFSET 0x040c +#define IMX9_FLEXIO_TIMCTL4_OFFSET 0x0410 +#define IMX9_FLEXIO_TIMCTL5_OFFSET 0x0414 +#define IMX9_FLEXIO_TIMCTL6_OFFSET 0x0418 +#define IMX9_FLEXIO_TIMCTL7_OFFSET 0x041c +#define IMX9_FLEXIO_TIMCTL_OFFSET(x) (IMX9_FLEXIO_TIMCTL0_OFFSET + (x) * 4) +#define IMX9_FLEXIO_TIMCFG0_OFFSET 0x0480 /* Timer Configuration N Register, array offset: 0x480, array step: 0x4 */ +#define IMX9_FLEXIO_TIMCFG1_OFFSET 0x0484 +#define IMX9_FLEXIO_TIMCFG2_OFFSET 0x0488 +#define IMX9_FLEXIO_TIMCFG3_OFFSET 0x048c +#define IMX9_FLEXIO_TIMCFG4_OFFSET 0x0490 +#define IMX9_FLEXIO_TIMCFG5_OFFSET 0x0494 +#define IMX9_FLEXIO_TIMCFG6_OFFSET 0x0498 +#define IMX9_FLEXIO_TIMCFG7_OFFSET 0x049c +#define IMX9_FLEXIO_TIMCFG_OFFSET(x) (IMX9_FLEXIO_TIMCFG0_OFFSET + (x) * 4) +#define IMX9_FLEXIO_TIMCMP0_OFFSET 0x0500 /* Timer Compare N Register, array offset: 0x500, array step: 0x4 */ +#define IMX9_FLEXIO_TIMCMP1_OFFSET 0x0504 +#define IMX9_FLEXIO_TIMCMP2_OFFSET 0x0508 +#define IMX9_FLEXIO_TIMCMP3_OFFSET 0x050c +#define IMX9_FLEXIO_TIMCMP4_OFFSET 0x0510 +#define IMX9_FLEXIO_TIMCMP5_OFFSET 0x0514 +#define IMX9_FLEXIO_TIMCMP6_OFFSET 0x0518 +#define IMX9_FLEXIO_TIMCMP7_OFFSET 0x051c +#define IMX9_FLEXIO_TIMCMP_OFFSET(x) (IMX9_FLEXIO_TIMCMP0_OFFSET + (x) * 4) +#define IMX9_FLEXIO_SHIFTBUFNBS0_OFFSET 0x0680 /* Shifter Buffer N Nibble Byte Swapped Register, array offset: 0x680, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFNBS1_OFFSET 0x0684 +#define IMX9_FLEXIO_SHIFTBUFNBS2_OFFSET 0x0688 +#define IMX9_FLEXIO_SHIFTBUFNBS3_OFFSET 0x068c +#define IMX9_FLEXIO_SHIFTBUFNBS4_OFFSET 0x0690 +#define IMX9_FLEXIO_SHIFTBUFNBS5_OFFSET 0x0694 +#define IMX9_FLEXIO_SHIFTBUFNBS6_OFFSET 0x0698 +#define IMX9_FLEXIO_SHIFTBUFNBS7_OFFSET 0x069c +#define IMX9_FLEXIO_SHIFTBUFHWS0_OFFSET 0x0700 /* Shifter Buffer N Half Word Swapped Register, array offset: 0x700, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFHWS1_OFFSET 0x0704 +#define IMX9_FLEXIO_SHIFTBUFHWS2_OFFSET 0x0708 +#define IMX9_FLEXIO_SHIFTBUFHWS3_OFFSET 0x070c +#define IMX9_FLEXIO_SHIFTBUFHWS4_OFFSET 0x0710 +#define IMX9_FLEXIO_SHIFTBUFHWS5_OFFSET 0x0714 +#define IMX9_FLEXIO_SHIFTBUFHWS6_OFFSET 0x0718 +#define IMX9_FLEXIO_SHIFTBUFHWS7_OFFSET 0x071c +#define IMX9_FLEXIO_SHIFTBUFNIS0_OFFSET 0x0780 /* Shifter Buffer N Nibble Swapped Register, array offset: 0x780, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFNIS1_OFFSET 0x0784 +#define IMX9_FLEXIO_SHIFTBUFNIS2_OFFSET 0x0788 +#define IMX9_FLEXIO_SHIFTBUFNIS3_OFFSET 0x078c +#define IMX9_FLEXIO_SHIFTBUFNIS4_OFFSET 0x0790 +#define IMX9_FLEXIO_SHIFTBUFNIS5_OFFSET 0x0794 +#define IMX9_FLEXIO_SHIFTBUFNIS6_OFFSET 0x0798 +#define IMX9_FLEXIO_SHIFTBUFNIS7_OFFSET 0x079c +#define IMX9_FLEXIO_SHIFTBUFOES0_OFFSET 0x0800 /* Shifter Buffer N Odd Even Swapped, array offset: 0x800, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFOES1_OFFSET 0x0804 +#define IMX9_FLEXIO_SHIFTBUFOES2_OFFSET 0x0808 +#define IMX9_FLEXIO_SHIFTBUFOES3_OFFSET 0x080c +#define IMX9_FLEXIO_SHIFTBUFOES4_OFFSET 0x0810 +#define IMX9_FLEXIO_SHIFTBUFOES5_OFFSET 0x0814 +#define IMX9_FLEXIO_SHIFTBUFOES6_OFFSET 0x0818 +#define IMX9_FLEXIO_SHIFTBUFOES7_OFFSET 0x081c +#define IMX9_FLEXIO_SHIFTBUFEOS0_OFFSET 0x0880 /* Shifter Buffer N Even Odd Swapped, array offset: 0x880, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFEOS1_OFFSET 0x0884 +#define IMX9_FLEXIO_SHIFTBUFEOS2_OFFSET 0x0888 +#define IMX9_FLEXIO_SHIFTBUFEOS3_OFFSET 0x088c +#define IMX9_FLEXIO_SHIFTBUFEOS4_OFFSET 0x0890 +#define IMX9_FLEXIO_SHIFTBUFEOS5_OFFSET 0x0894 +#define IMX9_FLEXIO_SHIFTBUFEOS6_OFFSET 0x0898 +#define IMX9_FLEXIO_SHIFTBUFEOS7_OFFSET 0x089c +#define IMX9_FLEXIO_SHIFTBUFHBS0_OFFSET 0x0900 /* Shifter Buffer N Halfword Byte Swapped, array offset: 0x900, array step: 0x4 */ +#define IMX9_FLEXIO_SHIFTBUFHBS1_OFFSET 0x0904 +#define IMX9_FLEXIO_SHIFTBUFHBS2_OFFSET 0x0908 +#define IMX9_FLEXIO_SHIFTBUFHBS3_OFFSET 0x090c +#define IMX9_FLEXIO_SHIFTBUFHBS4_OFFSET 0x0910 +#define IMX9_FLEXIO_SHIFTBUFHBS5_OFFSET 0x0914 +#define IMX9_FLEXIO_SHIFTBUFHBS6_OFFSET 0x0918 +#define IMX9_FLEXIO_SHIFTBUFHBS7_OFFSET 0x091c + +/* VERID - Version ID Register */ + +#define FLEXIO_VERID_FEATURE_MASK (0xffffu) +#define FLEXIO_VERID_FEATURE_SHIFT (0u) + +/* FEATURE - Feature Specification Number + * 0b0000000000000000..Standard features implemented. + * 0b0000000000000001..Supports state, logic and parallel modes. + */ + +#define FLEXIO_VERID_FEATURE(x) ((((uint32_t)(x)) << FLEXIO_VERID_FEATURE_SHIFT) & FLEXIO_VERID_FEATURE_MASK) + +#define FLEXIO_VERID_MINOR_MASK (0xff0000u) +#define FLEXIO_VERID_MINOR_SHIFT (16u) + +/* MINOR - Minor Version Number */ + +#define FLEXIO_VERID_MINOR(x) ((((uint32_t)(x)) << FLEXIO_VERID_MINOR_SHIFT) & FLEXIO_VERID_MINOR_MASK) + +#define FLEXIO_VERID_MAJOR_MASK (0xff000000u) +#define FLEXIO_VERID_MAJOR_SHIFT (24u) + +/* MAJOR - Major Version Number */ +#define FLEXIO_VERID_MAJOR(x) ((((uint32_t)(x)) << FLEXIO_VERID_MAJOR_SHIFT) & FLEXIO_VERID_MAJOR_MASK) + +/* PARAM - Parameter Register */ + +#define FLEXIO_PARAM_SHIFTER_MASK (0xffu) +#define FLEXIO_PARAM_SHIFTER_SHIFT (0u) + +/* SHIFTER - Shifter Number */ +#define FLEXIO_PARAM_SHIFTER(x) ((((uint32_t)(x)) << FLEXIO_PARAM_SHIFTER_SHIFT) & FLEXIO_PARAM_SHIFTER_MASK) + +#define FLEXIO_PARAM_TIMER_MASK (0xff00u) +#define FLEXIO_PARAM_TIMER_SHIFT (8u) + +/* TIMER - Timer Number */ + +#define FLEXIO_PARAM_TIMER(x) ((((uint32_t)(x)) << FLEXIO_PARAM_TIMER_SHIFT) & FLEXIO_PARAM_TIMER_MASK) + +#define FLEXIO_PARAM_PIN_MASK (0xff0000u) +#define FLEXIO_PARAM_PIN_SHIFT (16u) + +/* PIN - Pin Number */ +#define FLEXIO_PARAM_PIN(x) ((((uint32_t)(x)) << FLEXIO_PARAM_PIN_SHIFT) & FLEXIO_PARAM_PIN_MASK) + +#define FLEXIO_PARAM_TRIGGER_MASK (0xff000000u) +#define FLEXIO_PARAM_TRIGGER_SHIFT (24u) + +/* TRIGGER - Trigger Number */ + +#define FLEXIO_PARAM_TRIGGER(x) ((((uint32_t)(x)) << FLEXIO_PARAM_TRIGGER_SHIFT) & FLEXIO_PARAM_TRIGGER_MASK) + +/* CTRL - FlexIO Control Register */ + +#define FLEXIO_CTRL_FLEXEN_MASK (0x1u) +#define FLEXIO_CTRL_FLEXEN_SHIFT (0u) + +/* FLEXEN - FlexIO Enable + * 0b0..FlexIO module is disabled. + * 0b1..FlexIO module is enabled. + */ + +#define FLEXIO_CTRL_FLEXEN(x) ((((uint32_t)(x)) << FLEXIO_CTRL_FLEXEN_SHIFT) & FLEXIO_CTRL_FLEXEN_MASK) + +#define FLEXIO_CTRL_SWRST_MASK (0x2u) +#define FLEXIO_CTRL_SWRST_SHIFT (1u) + +/* SWRST - Software Reset + * 0b0..Software reset is disabled + * 0b1..Software reset is enabled, all FlexIO registers except the Control + * Register are reset. + */ + +#define FLEXIO_CTRL_SWRST(x) ((((uint32_t)(x)) << FLEXIO_CTRL_SWRST_SHIFT) & FLEXIO_CTRL_SWRST_MASK) + +#define FLEXIO_CTRL_FASTACC_MASK (0x4u) +#define FLEXIO_CTRL_FASTACC_SHIFT (2u) + +/* FASTACC - Fast Access + * 0b0..Configures for normal register accesses to FlexIO + * 0b1..Configures for fast register accesses to FlexIO + */ + +#define FLEXIO_CTRL_FASTACC(x) ((((uint32_t)(x)) << FLEXIO_CTRL_FASTACC_SHIFT) & FLEXIO_CTRL_FASTACC_MASK) + +#define FLEXIO_CTRL_DBGE_MASK (0x40000000u) +#define FLEXIO_CTRL_DBGE_SHIFT (30u) + +/* DBGE - Debug Enable + * 0b0..FlexIO is disabled in debug modes. + * 0b1..FlexIO is enabled in debug modes + */ + +#define FLEXIO_CTRL_DBGE(x) ((((uint32_t)(x)) << FLEXIO_CTRL_DBGE_SHIFT) & FLEXIO_CTRL_DBGE_MASK) + +#define FLEXIO_CTRL_DOZEN_MASK (0x80000000u) +#define FLEXIO_CTRL_DOZEN_SHIFT (31u) + +/* DOZEN - Doze Enable + * 0b0..FlexIO enabled in Doze modes. + * 0b1..FlexIO disabled in Doze modes. + */ + +#define FLEXIO_CTRL_DOZEN(x) ((((uint32_t)(x)) << FLEXIO_CTRL_DOZEN_SHIFT) & FLEXIO_CTRL_DOZEN_MASK) + +/* PIN - Pin State Register */ + +#define FLEXIO_PIN_PDI_MASK (0xffffffffu) /* Merged from fields with different position or width, of widths (16, 32), largest definition used */ +#define FLEXIO_PIN_PDI_SHIFT (0u) + +/* PDI - Pin Data Input */ + +#define FLEXIO_PIN_PDI(x) ((((uint32_t)(x)) << FLEXIO_PIN_PDI_SHIFT) & FLEXIO_PIN_PDI_MASK) /* Merged from fields with different position or width, of widths (16, 32), largest definition used */ + +/* SHIFTSTAT - Shifter Status Register */ + +#define FLEXIO_SHIFTSTAT_SSF_MASK (0xffu) +#define FLEXIO_SHIFTSTAT_SSF_SHIFT (0u) + +/* SSF - Shifter Status Flag */ + +#define FLEXIO_SHIFTSTAT_SSF(x) ((((uint32_t)(x)) << FLEXIO_SHIFTSTAT_SSF_SHIFT) & FLEXIO_SHIFTSTAT_SSF_MASK) + +/* SHIFTERR - Shifter Error Register */ + +#define FLEXIO_SHIFTERR_SEF_MASK (0xffu) +#define FLEXIO_SHIFTERR_SEF_SHIFT (0u) + +/* SEF - Shifter Error Flags */ + +#define FLEXIO_SHIFTERR_SEF(x) ((((uint32_t)(x)) << FLEXIO_SHIFTERR_SEF_SHIFT) & FLEXIO_SHIFTERR_SEF_MASK) + +/* TIMSTAT - Timer Status Register */ + +#define FLEXIO_TIMSTAT_TSF_MASK (0xffu) +#define FLEXIO_TIMSTAT_TSF_SHIFT (0u) + +/* TSF - Timer Status Flags */ + +#define FLEXIO_TIMSTAT_TSF(x) ((((uint32_t)(x)) << FLEXIO_TIMSTAT_TSF_SHIFT) & FLEXIO_TIMSTAT_TSF_MASK) + +/* SHIFTSIEN - Shifter Status Interrupt Enable */ + +#define FLEXIO_SHIFTSIEN_SSIE_MASK (0xffu) +#define FLEXIO_SHIFTSIEN_SSIE_SHIFT (0u) + +/* SSIE - Shifter Status Interrupt Enable */ + +#define FLEXIO_SHIFTSIEN_SSIE(x) ((((uint32_t)(x)) << FLEXIO_SHIFTSIEN_SSIE_SHIFT) & FLEXIO_SHIFTSIEN_SSIE_MASK) + +/* SHIFTEIEN - Shifter Error Interrupt Enable */ + +#define FLEXIO_SHIFTEIEN_SEIE_MASK (0xffu) +#define FLEXIO_SHIFTEIEN_SEIE_SHIFT (0u) + +/* SEIE - Shifter Error Interrupt Enable */ + +#define FLEXIO_SHIFTEIEN_SEIE(x) ((((uint32_t)(x)) << FLEXIO_SHIFTEIEN_SEIE_SHIFT) & FLEXIO_SHIFTEIEN_SEIE_MASK) + +/* TIMIEN - Timer Interrupt Enable Register */ + +#define FLEXIO_TIMIEN_TEIE_MASK (0xffu) +#define FLEXIO_TIMIEN_TEIE_SHIFT (0u) + +/* TEIE - Timer Status Interrupt Enable */ + +#define FLEXIO_TIMIEN_TEIE(x) ((((uint32_t)(x)) << FLEXIO_TIMIEN_TEIE_SHIFT) & FLEXIO_TIMIEN_TEIE_MASK) + +/* SHIFTSDEN - Shifter Status DMA Enable */ + +#define FLEXIO_SHIFTSDEN_SSDE_MASK (0xffu) +#define FLEXIO_SHIFTSDEN_SSDE_SHIFT (0u) + +/* SSDE - Shifter Status DMA Enable */ + +#define FLEXIO_SHIFTSDEN_SSDE(x) ((((uint32_t)(x)) << FLEXIO_SHIFTSDEN_SSDE_SHIFT) & FLEXIO_SHIFTSDEN_SSDE_MASK) + +/* TIMERSDEN - Timer Status DMA Enable */ + +#define FLEXIO_TIMERSDEN_TSDE_MASK (0xffu) +#define FLEXIO_TIMERSDEN_TSDE_SHIFT (0u) + +/* TSDE - Timer Status DMA Enable */ + +#define FLEXIO_TIMERSDEN_TSDE(x) ((((uint32_t)(x)) << FLEXIO_TIMERSDEN_TSDE_SHIFT) & FLEXIO_TIMERSDEN_TSDE_MASK) + +/* SHIFTSTATE - Shifter State Register */ + +#define FLEXIO_SHIFTSTATE_STATE_MASK (0x7u) +#define FLEXIO_SHIFTSTATE_STATE_SHIFT (0u) + +/* STATE - Current State Pointer */ + +#define FLEXIO_SHIFTSTATE_STATE(x) ((((uint32_t)(x)) << FLEXIO_SHIFTSTATE_STATE_SHIFT) & FLEXIO_SHIFTSTATE_STATE_MASK) + +/* TRGSTAT - Trigger Status */ + +#define FLEXIO_TRGSTAT_ETSF_MASK (0xfu) +#define FLEXIO_TRGSTAT_ETSF_SHIFT (0u) + +#define FLEXIO_TRGSTAT_ETSF(x) ((((uint32_t)(x)) << FLEXIO_TRGSTAT_ETSF_SHIFT) & FLEXIO_TRGSTAT_ETSF_MASK) + +/* TRIGIEN - External Trigger Interrupt Enable */ + +#define FLEXIO_TRIGIEN_TRIE_MASK (0xfu) +#define FLEXIO_TRIGIEN_TRIE_SHIFT (0u) + +#define FLEXIO_TRIGIEN_TRIE(x) ((((uint32_t)(x)) << FLEXIO_TRIGIEN_TRIE_SHIFT) & FLEXIO_TRIGIEN_TRIE_MASK) + +/* SHIFTCTL - Shifter Control N Register */ + +#define FLEXIO_SHIFTCTL_SMOD_MASK (0x7u) +#define FLEXIO_SHIFTCTL_SMOD_SHIFT (0u) + +/* SMOD - Shifter Mode + * 0b000..Disabled. + * 0b001..Receive mode. Captures the current Shifter content into the + * SHIFTBUF on expiration of the Timer. + * 0b010..Transmit mode. Load SHIFTBUF contents into the Shifter on + * expiration of the Timer. + * 0b011..Reserved. + * 0b100..Match Store mode. Shifter data is compared to SHIFTBUF content on + * expiration of the Timer. + * 0b101..Match Continuous mode. Shifter data is continuously compared to + * SHIFTBUF contents. + * 0b110..State mode. SHIFTBUF contents are used for storing programmable + * state attributes. + * 0b111..Logic mode. SHIFTBUF contents are used for implementing + * programmable logic look up table. + */ + +#define FLEXIO_SHIFTCTL_SMOD(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCTL_SMOD_SHIFT) & FLEXIO_SHIFTCTL_SMOD_MASK) + +#define FLEXIO_SHIFTCTL_PINPOL_MASK (0x80u) +#define FLEXIO_SHIFTCTL_PINPOL_SHIFT (7u) + +/* PINPOL - Shifter Pin Polarity + * 0b0..Pin is active high + * 0b1..Pin is active low + */ + +#define FLEXIO_SHIFTCTL_PINPOL(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCTL_PINPOL_SHIFT) & FLEXIO_SHIFTCTL_PINPOL_MASK) + +#define FLEXIO_SHIFTCTL_PINSEL_MASK (0x1f00u) /* Merged from fields with different position or width, of widths (4, 5), largest definition used */ +#define FLEXIO_SHIFTCTL_PINSEL_SHIFT (8u) + +/* PINSEL - Shifter Pin Select */ + +#define FLEXIO_SHIFTCTL_PINSEL(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCTL_PINSEL_SHIFT) & FLEXIO_SHIFTCTL_PINSEL_MASK) /* Merged from fields with different position or width, of widths (4, 5), largest definition used */ + +#define FLEXIO_SHIFTCTL_PINCFG_MASK (0x30000u) +#define FLEXIO_SHIFTCTL_PINCFG_SHIFT (16u) + +/* PINCFG - Shifter Pin Configuration + * 0b00..Shifter pin output disabled + * 0b01..Shifter pin open drain or bidirectional output enable + * 0b10..Shifter pin bidirectional output data + * 0b11..Shifter pin output + */ + +#define FLEXIO_SHIFTCTL_PINCFG(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCTL_PINCFG_SHIFT) & FLEXIO_SHIFTCTL_PINCFG_MASK) + +#define FLEXIO_SHIFTCTL_TIMPOL_MASK (0x800000u) +#define FLEXIO_SHIFTCTL_TIMPOL_SHIFT (23u) + +/* TIMPOL - Timer Polarity + * 0b0..Shift on posedge of Shift clock + * 0b1..Shift on negedge of Shift clock + */ + +#define FLEXIO_SHIFTCTL_TIMPOL(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCTL_TIMPOL_SHIFT) & FLEXIO_SHIFTCTL_TIMPOL_MASK) + +#define FLEXIO_SHIFTCTL_TIMSEL_MASK (0x7000000u) +#define FLEXIO_SHIFTCTL_TIMSEL_SHIFT (24u) + +/* TIMSEL - Timer Select */ + +#define FLEXIO_SHIFTCTL_TIMSEL(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCTL_TIMSEL_SHIFT) & FLEXIO_SHIFTCTL_TIMSEL_MASK) + +/* The count of FLEXIO_SHIFTCTL */ + +#define FLEXIO_SHIFTCTL_COUNT (8u) + +/* SHIFTCFG - Shifter Configuration N Register */ + +#define FLEXIO_SHIFTCFG_SSTART_MASK (0x3u) +#define FLEXIO_SHIFTCFG_SSTART_SHIFT (0u) + +/* SSTART - Shifter Start bit + * 0b00..Start bit disabled for transmitter/receiver/match store, + * transmitter loads data on enable + * 0b01..Start bit disabled for transmitter/receiver/match store, + * transmitter loads data on first shift + * 0b10..Transmitter outputs start bit value 0 before loading data on first + * shift, receiver/match store sets error flag if start bit is not 0 + * 0b11..Transmitter outputs start bit value 1 before loading data on first + * shift, receiver/match store sets error flag if start bit is not 1 + */ + +#define FLEXIO_SHIFTCFG_SSTART(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCFG_SSTART_SHIFT) & FLEXIO_SHIFTCFG_SSTART_MASK) + +#define FLEXIO_SHIFTCFG_SSTOP_MASK (0x30u) +#define FLEXIO_SHIFTCFG_SSTOP_SHIFT (4u) + +/* SSTOP - Shifter Stop bit + * 0b00..Stop bit disabled for transmitter/receiver/match store + * 0b01..Reserved for transmitter/receiver/match store + * 0b10..Transmitter outputs stop bit value 0 on store, receiver/match store + * sets error flag if stop bit is not 0 + * 0b11..Transmitter outputs stop bit value 1 on store, receiver/match store + * sets error flag if stop bit is not 1 + */ + +#define FLEXIO_SHIFTCFG_SSTOP(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCFG_SSTOP_SHIFT) & FLEXIO_SHIFTCFG_SSTOP_MASK) + +#define FLEXIO_SHIFTCFG_INSRC_MASK (0x100u) +#define FLEXIO_SHIFTCFG_INSRC_SHIFT (8u) + +/* INSRC - Input Source + * 0b0..Pin + * 0b1..Shifter N+1 Output + */ + +#define FLEXIO_SHIFTCFG_INSRC(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCFG_INSRC_SHIFT) & FLEXIO_SHIFTCFG_INSRC_MASK) + +/* LATST - Late Store */ + +#define FLEXIO_SHIFTCFG_LATST_MASK (0x200u) +#define FLEXIO_SHIFTCFG_LATST_SHIFT (9u) + +#define FLEXIO_SHIFTCFG_LATST(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCFG_LATST_SHIFT) & FLEXIO_SHIFTCFG_LATST_MASK) + +/* SSIZE - Shifter Size */ + +#define FLEXIO_SHIFTCFG_SSIZE_MASK (0x1000u) +#define FLEXIO_SHIFTCFG_SSIZE_SHIFT (12u) + +#define FLEXIO_SHIFTCFG_SSIZE(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCFG_SSIZE_SHIFT) & FLEXIO_SHIFTCFG_SSIZE_MASK) + +#define FLEXIO_SHIFTCFG_PWIDTH_MASK (0x1f0000u) /* Merged from fields with different position or width, of widths (4, 5), largest definition used */ +#define FLEXIO_SHIFTCFG_PWIDTH_SHIFT (16u) + +/* PWIDTH - Parallel Width */ + +#define FLEXIO_SHIFTCFG_PWIDTH(x) ((((uint32_t)(x)) << FLEXIO_SHIFTCFG_PWIDTH_SHIFT) & FLEXIO_SHIFTCFG_PWIDTH_MASK) /* Merged from fields with different position or width, of widths (4, 5), largest definition used */ + +/* The count of FLEXIO_SHIFTCFG */ + +#define FLEXIO_SHIFTCFG_COUNT (8u) + +/* SHIFTBUF - Shifter Buffer N Register */ + +#define FLEXIO_SHIFTBUF_SHIFTBUF_MASK (0xffffffffu) +#define FLEXIO_SHIFTBUF_SHIFTBUF_SHIFT (0u) + +/* SHIFTBUF - Shift Buffer */ + +#define FLEXIO_SHIFTBUF_SHIFTBUF(x) ((((uint32_t)(x)) << FLEXIO_SHIFTBUF_SHIFTBUF_SHIFT) & FLEXIO_SHIFTBUF_SHIFTBUF_MASK) + +/* The count of FLEXIO_SHIFTBUF */ + +#define FLEXIO_SHIFTBUF_COUNT (8u) + +/* SHIFTBUFBIS - Shifter Buffer N Bit Swapped Register */ + +#define FLEXIO_SHIFTBUFBIS_SHIFTBUFBIS_MASK (0xffffffffu) +#define FLEXIO_SHIFTBUFBIS_SHIFTBUFBIS_SHIFT (0u) + +/* SHIFTBUFBIS - Shift Buffer */ + +#define FLEXIO_SHIFTBUFBIS_SHIFTBUFBIS(x) ((((uint32_t)(x)) << FLEXIO_SHIFTBUFBIS_SHIFTBUFBIS_SHIFT) & FLEXIO_SHIFTBUFBIS_SHIFTBUFBIS_MASK) + +/* The count of FLEXIO_SHIFTBUFBIS */ + +#define FLEXIO_SHIFTBUFBIS_COUNT (8u) + +/* SHIFTBUFBYS - Shifter Buffer N Byte Swapped Register */ + +#define FLEXIO_SHIFTBUFBYS_SHIFTBUFBYS_MASK (0xffffffffu) +#define FLEXIO_SHIFTBUFBYS_SHIFTBUFBYS_SHIFT (0u) + +/* SHIFTBUFBYS - Shift Buffer */ + +#define FLEXIO_SHIFTBUFBYS_SHIFTBUFBYS(x) ((((uint32_t)(x)) << FLEXIO_SHIFTBUFBYS_SHIFTBUFBYS_SHIFT) & FLEXIO_SHIFTBUFBYS_SHIFTBUFBYS_MASK) + +/* The count of FLEXIO_SHIFTBUFBYS */ + +#define FLEXIO_SHIFTBUFBYS_COUNT (8u) + +/* SHIFTBUFBBS - Shifter Buffer N Bit Byte Swapped Register */ + +#define FLEXIO_SHIFTBUFBBS_SHIFTBUFBBS_MASK (0xffffffffu) +#define FLEXIO_SHIFTBUFBBS_SHIFTBUFBBS_SHIFT (0u) + +/* SHIFTBUFBBS - Shift Buffer */ + +#define FLEXIO_SHIFTBUFBBS_SHIFTBUFBBS(x) ((((uint32_t)(x)) << FLEXIO_SHIFTBUFBBS_SHIFTBUFBBS_SHIFT) & FLEXIO_SHIFTBUFBBS_SHIFTBUFBBS_MASK) + +/* The count of FLEXIO_SHIFTBUFBBS */ + +#define FLEXIO_SHIFTBUFBBS_COUNT (8u) + +/* TIMCTL - Timer Control N Register */ + +#define FLEXIO_TIMCTL_TIMOD_MASK (0x3u) +#define FLEXIO_TIMCTL_TIMOD_SHIFT (0u) + +/* TIMOD - Timer Mode + * 0b000..Timer Disabled. + * 0b001..Dual 8-bit counters baud mode. + * 0b010..Dual 8-bit counters PWM high mode. + * 0b011..Single 16-bit counter mode. + * 0b100..Single 16-bit counter disable mode. + * 0b101..Dual 8-bit counters word mode. + * 0b110..Dual 8-bit counters PWM low mode. + * 0b111..Single 16-bit input capture mode. + */ + +#define FLEXIO_TIMCTL_TIMOD(x) ((((uint32_t)(x)) << FLEXIO_TIMCTL_TIMOD_SHIFT) & FLEXIO_TIMCTL_TIMOD_MASK) + +#define FLEXIO_TIMCTL_PINPOL_MASK (0x80u) +#define FLEXIO_TIMCTL_PINPOL_SHIFT (7u) + +/* PINPOL - Timer Pin Polarity + * 0b0..Pin is active high + * 0b1..Pin is active low + */ + +#define FLEXIO_TIMCTL_PINPOL(x) ((((uint32_t)(x)) << FLEXIO_TIMCTL_PINPOL_SHIFT) & FLEXIO_TIMCTL_PINPOL_MASK) + +#define FLEXIO_TIMCTL_PINSEL_MASK (0x1f00u) /* Merged from fields with different position or width, of widths (4, 5), largest definition used */ +#define FLEXIO_TIMCTL_PINSEL_SHIFT (8u) + +/* PINSEL - Timer Pin Select */ + +#define FLEXIO_TIMCTL_PINSEL(x) ((((uint32_t)(x)) << FLEXIO_TIMCTL_PINSEL_SHIFT) & FLEXIO_TIMCTL_PINSEL_MASK) /* Merged from fields with different position or width, of widths (4, 5), largest definition used */ + +#define FLEXIO_TIMCTL_PINCFG_MASK (0x30000u) +#define FLEXIO_TIMCTL_PINCFG_SHIFT (16u) + +/* PINCFG - Timer Pin Configuration + * 0b00..Timer pin output disabled + * 0b01..Timer pin open drain or bidirectional output enable + * 0b10..Timer pin bidirectional output data + * 0b11..Timer pin output + */ + +#define FLEXIO_TIMCTL_PINCFG(x) ((((uint32_t)(x)) << FLEXIO_TIMCTL_PINCFG_SHIFT) & FLEXIO_TIMCTL_PINCFG_MASK) + +#define FLEXIO_TIMCTL_TRGSRC_MASK (0x400000u) +#define FLEXIO_TIMCTL_TRGSRC_SHIFT (22u) + +/* TRGSRC - Trigger Source + * 0b0..External trigger selected + * 0b1..Internal trigger selected + */ + +#define FLEXIO_TIMCTL_TRGSRC(x) ((((uint32_t)(x)) << FLEXIO_TIMCTL_TRGSRC_SHIFT) & FLEXIO_TIMCTL_TRGSRC_MASK) + +#define FLEXIO_TIMCTL_TRGPOL_MASK (0x800000u) +#define FLEXIO_TIMCTL_TRGPOL_SHIFT (23u) + +/* TRGPOL - Trigger Polarity + * 0b0..Trigger active high + * 0b1..Trigger active low + */ + +#define FLEXIO_TIMCTL_TRGPOL(x) ((((uint32_t)(x)) << FLEXIO_TIMCTL_TRGPOL_SHIFT) & FLEXIO_TIMCTL_TRGPOL_MASK) + +#define FLEXIO_TIMCTL_TRGSEL_MASK (0x3f000000u) /* Merged from fields with different position or width, of widths (5, 6), largest definition used */ +#define FLEXIO_TIMCTL_TRGSEL_SHIFT (24u) + +/* TRGSEL - Trigger Select */ + +#define FLEXIO_TIMCTL_TRGSEL(x) ((((uint32_t)(x)) << FLEXIO_TIMCTL_TRGSEL_SHIFT) & FLEXIO_TIMCTL_TRGSEL_MASK) /* Merged from fields with different position or width, of widths (5, 6), largest definition used */ + +/* The count of FLEXIO_TIMCTL */ + +#define FLEXIO_TIMCTL_COUNT (8u) + +/* TIMCFG - Timer Configuration N Register */ + +#define FLEXIO_TIMCFG_TSTART_MASK (0x2u) +#define FLEXIO_TIMCFG_TSTART_SHIFT (1u) + +/* TSTART - Timer Start Bit + * 0b0..Start bit disabled + * 0b1..Start bit enabled + */ + +#define FLEXIO_TIMCFG_TSTART(x) ((((uint32_t)(x)) << FLEXIO_TIMCFG_TSTART_SHIFT) & FLEXIO_TIMCFG_TSTART_MASK) + +#define FLEXIO_TIMCFG_TSTOP_MASK (0x30u) +#define FLEXIO_TIMCFG_TSTOP_SHIFT (4u) + +/* TSTOP - Timer Stop Bit + * 0b00..Stop bit disabled + * 0b01..Stop bit is enabled on timer compare + * 0b10..Stop bit is enabled on timer disable + * 0b11..Stop bit is enabled on timer compare and timer disable + */ + +#define FLEXIO_TIMCFG_TSTOP(x) ((((uint32_t)(x)) << FLEXIO_TIMCFG_TSTOP_SHIFT) & FLEXIO_TIMCFG_TSTOP_MASK) + +#define FLEXIO_TIMCFG_TIMENA_MASK (0x700u) +#define FLEXIO_TIMCFG_TIMENA_SHIFT (8u) + +/* TIMENA - Timer Enable + * 0b000..Timer always enabled + * 0b001..Timer enabled on Timer N-1 enable + * 0b010..Timer enabled on Trigger high + * 0b011..Timer enabled on Trigger high and Pin high + * 0b100..Timer enabled on Pin rising edge + * 0b101..Timer enabled on Pin rising edge and Trigger high + * 0b110..Timer enabled on Trigger rising edge + * 0b111..Timer enabled on Trigger rising or falling edge + */ + +#define FLEXIO_TIMCFG_TIMENA(x) ((((uint32_t)(x)) << FLEXIO_TIMCFG_TIMENA_SHIFT) & FLEXIO_TIMCFG_TIMENA_MASK) + +#define FLEXIO_TIMCFG_TIMDIS_MASK (0x7000u) +#define FLEXIO_TIMCFG_TIMDIS_SHIFT (12u) + +/* TIMDIS - Timer Disable + * 0b000..Timer never disabled + * 0b001..Timer disabled on Timer N-1 disable + * 0b010..Timer disabled on Timer compare (upper 8-bits match and decrement) + * 0b011..Timer disabled on Timer compare (upper 8-bits match and decrement) + * and Trigger Low + * 0b100..Timer disabled on Pin rising or falling edge + * 0b101..Timer disabled on Pin rising or falling edge provided Trigger is + * high + * 0b110..Timer disabled on Trigger falling edge + * 0b111..Reserved + */ + +#define FLEXIO_TIMCFG_TIMDIS(x) ((((uint32_t)(x)) << FLEXIO_TIMCFG_TIMDIS_SHIFT) & FLEXIO_TIMCFG_TIMDIS_MASK) + +#define FLEXIO_TIMCFG_TIMRST_MASK (0x70000u) +#define FLEXIO_TIMCFG_TIMRST_SHIFT (16u) + +/* TIMRST - Timer Reset + * 0b000..Timer never reset + * 0b001..Reserved + * 0b010..Timer reset on Timer Pin equal to Timer Output + * 0b011..Timer reset on Timer Trigger equal to Timer Output + * 0b100..Timer reset on Timer Pin rising edge + * 0b101..Reserved + * 0b110..Timer reset on Trigger rising edge + * 0b111..Timer reset on Trigger rising or falling edge + */ + +#define FLEXIO_TIMCFG_TIMRST(x) ((((uint32_t)(x)) << FLEXIO_TIMCFG_TIMRST_SHIFT) & FLEXIO_TIMCFG_TIMRST_MASK) + +#define FLEXIO_TIMCFG_TIMDEC_MASK (0x300000u) +#define FLEXIO_TIMCFG_TIMDEC_SHIFT (20U) + +/* TIMDEC - Timer Decrement + * 0b00..Decrement counter on FlexIO clock, Shift clock equals Timer output. + * 0b01..Decrement counter on Trigger input (both edges), Shift clock equals + * Timer output. + * 0b10..Decrement counter on Pin input (both edges), Shift clock equals Pin + * input. + * 0b11..Decrement counter on Trigger input (both edges), Shift clock equals + * Trigger input. + */ + +#define FLEXIO_TIMCFG_TIMDEC(x) ((((uint32_t)(x)) << FLEXIO_TIMCFG_TIMDEC_SHIFT) & FLEXIO_TIMCFG_TIMDEC_MASK) + +#define FLEXIO_TIMCFG_TIMOUT_MASK (0x3000000u) +#define FLEXIO_TIMCFG_TIMOUT_SHIFT (24u) + +/* TIMOUT - Timer Output + * 0b00..Timer output is logic one when enabled and is not affected by timer + * reset + * 0b01..Timer output is logic zero when enabled and is not affected by + * timer reset + * 0b10..Timer output is logic one when enabled and on timer reset + * 0b11..Timer output is logic zero when enabled and on timer reset + */ + +#define FLEXIO_TIMCFG_TIMOUT(x) ((((uint32_t)(x)) << FLEXIO_TIMCFG_TIMOUT_SHIFT) & FLEXIO_TIMCFG_TIMOUT_MASK) + +/* The count of FLEXIO_TIMCFG */ + +#define FLEXIO_TIMCFG_COUNT (8u) + +/* TIMCMP - Timer Compare N Register */ + +#define FLEXIO_TIMCMP_CMP_MASK (0xffffu) +#define FLEXIO_TIMCMP_CMP_SHIFT (0u) + +/* CMP - Timer Compare Value */ + +#define FLEXIO_TIMCMP_CMP(x) ((((uint32_t)(x)) << FLEXIO_TIMCMP_CMP_SHIFT) & FLEXIO_TIMCMP_CMP_MASK) + +/* The count of FLEXIO_TIMCMP */ + +#define FLEXIO_TIMCMP_COUNT (8u) + +/* SHIFTBUFNBS - Shifter Buffer N Nibble Byte Swapped Register */ + +#define FLEXIO_SHIFTBUFNBS_SHIFTBUFNBS_MASK (0xffffffffu) +#define FLEXIO_SHIFTBUFNBS_SHIFTBUFNBS_SHIFT (0u) + +/* SHIFTBUFNBS - Shift Buffer */ + +#define FLEXIO_SHIFTBUFNBS_SHIFTBUFNBS(x) ((((uint32_t)(x)) << FLEXIO_SHIFTBUFNBS_SHIFTBUFNBS_SHIFT) & FLEXIO_SHIFTBUFNBS_SHIFTBUFNBS_MASK) + +/* The count of FLEXIO_SHIFTBUFNBS */ + +#define FLEXIO_SHIFTBUFNBS_COUNT (8u) + +/* SHIFTBUFHWS - Shifter Buffer N Half Word Swapped Register */ + +#define FLEXIO_SHIFTBUFHWS_SHIFTBUFHWS_MASK (0xffffffffu) +#define FLEXIO_SHIFTBUFHWS_SHIFTBUFHWS_SHIFT (0u) + +/* SHIFTBUFHWS - Shift Buffer */ + +#define FLEXIO_SHIFTBUFHWS_SHIFTBUFHWS(x) ((((uint32_t)(x)) << FLEXIO_SHIFTBUFHWS_SHIFTBUFHWS_SHIFT) & FLEXIO_SHIFTBUFHWS_SHIFTBUFHWS_MASK) + +/* The count of FLEXIO_SHIFTBUFHWS */ + +#define FLEXIO_SHIFTBUFHWS_COUNT (8u) + +/* SHIFTBUFNIS - Shifter Buffer N Nibble Swapped Register */ + +#define FLEXIO_SHIFTBUFNIS_SHIFTBUFNIS_MASK (0xffffffffu) +#define FLEXIO_SHIFTBUFNIS_SHIFTBUFNIS_SHIFT (0u) + +/* SHIFTBUFNIS - Shift Buffer */ + +#define FLEXIO_SHIFTBUFNIS_SHIFTBUFNIS(x) ((((uint32_t)(x)) << FLEXIO_SHIFTBUFNIS_SHIFTBUFNIS_SHIFT) & FLEXIO_SHIFTBUFNIS_SHIFTBUFNIS_MASK) + +/* The count of FLEXIO_SHIFTBUFNIS */ + +#define FLEXIO_SHIFTBUFNIS_COUNT (8u) + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_FLEXIO_H */ diff --git a/arch/arm64/src/imx9/hardware/imx9_gpio.h b/arch/arm64/src/imx9/hardware/imx9_gpio.h new file mode 100644 index 0000000000000..b13be0eaf6b6a --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_gpio.h @@ -0,0 +1,106 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_IMX9_HARDWARE_IMX9_GPIO_H +#define __ARCH_ARM_SRC_IMX9_HARDWARE_IMX9_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_ARCH_CHIP_IMX93) +# include "hardware/imx93/imx93_gpio.h" +#else +# error Unrecognized i.MX9 architecture +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GPIO1 0 /* Port 1 index */ +#define GPIO2 1 /* Port 2 index */ +#define GPIO3 2 /* Port 3 index */ +#define GPIO4 3 /* Port 4 index */ +#define GPIO5 4 /* Port 5 index */ +#define GPIO6 5 /* Port 6 index */ +#define GPIO7 6 /* Port 7 index */ +#define GPIO8 7 /* Port 8 index */ +#define GPIO9 8 /* Port 9 index */ +#define GPIO10 9 /* Port 10 index */ +#define GPIO11 10 /* Port 11 index */ +#define GPIO12 11 /* Port 12 index */ +#define GPIO13 12 /* Port 13 index */ + +#define IMX9_GPIO_NPINS 32 /* Up to 32 pins per port */ + +/* Register bit definitions *************************************************/ + +/* Most registers are laid out simply with one bit per pin */ + +#define GPIO_PIN(n) (1 << (n)) /* Bit n: Pin n, n=0-31 */ + +/* ICRN Register */ + +#define IMX9_GPIO_ICRN_ISF (1 << 24) /* Bit 24: Interrupt Status Flag */ +#define IMX9_GPIO_ICRN_LK (1 << 23) /* Bit 23: Lock Register */ +#define IMX9_GPIO_ICRN_IRQS (1 << 20) /* Bit 20: Configures the selected interrupt, or DMA request. */ +#define IMX9_GPIO_ICRN_SHIFT (16) /* Bits 16-19: Interrupt Configuration */ +#define IMX9_GPIO_ICRN_MASK (0xf << IMX9_GPIO_ICRN_SHIFT) +# define IMX9_GPIO_ICRN_DISABLED (0 << IMX9_GPIO_ICRN_SHIFT) /* Interrupt Status Flag (ISF) is disabled */ +# define IMX9_GPIO_ICRN_DMARISING (1 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag and DMA request on rising edge */ +# define IMX9_GPIO_ICRN_DMAFALLING (2 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag and DMA request on falling edge */ +# define IMX9_GPIO_ICRN_DMABOTH (3 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag and DMA request on either edge */ +# define IMX9_GPIO_ICRN_ISFRISING (5 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag sets on rising edge */ +# define IMX9_GPIO_ICRN_ISFFALLING (6 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag sets on falling edge */ +# define IMX9_GPIO_ICRN_ISFBOTH (7 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag sets on either edge */ +# define IMX9_GPIO_ICRN_ZERO (8 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag and Interrupt when logic 0 */ +# define IMX9_GPIO_ICRN_RISING (9 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag and Interrupt on rising-edge */ +# define IMX9_GPIO_ICRN_FALLING (10 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag and Interrupt on falling-edge */ +# define IMX9_GPIO_ICRN_BOTH (11 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag and Interrupt on either edge */ +# define IMX9_GPIO_ICRN_ONE (12 << IMX9_GPIO_ICRN_SHIFT) /* ISF flag and Interrupt when logic 1 */ + +/* Global Interrupt Control Low Register */ + +#define IMX9_GPIO_GICLR_GIWD_SHIFT (0) /* Bits 0-15: Global Interrupt Write Data */ +#define IMX9_GPIO_GICLR_GIWD_MASK (0xffff << IMX9_GPIO_GICLR_GIWD_SHIFT) +# define IMX9_GPIO_GICLR_GIWD_PIN(n) ((uint32_t)(n) << IMX9_GPIO_GICLR_GIWD_SHIFT) /* Pin n=0..15 */ + +#define IMX9_GPIO_GICLR_GIWE_SHIFT (16) /* Bits 16-31: Global Interrupt Write Enable */ +#define IMX9_GPIO_GICLR_GIWE_MASK (0xffff << IMX9_GPIO_GICLR_GIWE_SHIFT) +# define IMX9_GPIO_GICLR_GIWE_PIN(n) ((uint32_t)(n) << IMX9_GPIO_GICLR_GIWE_SHIFT) /* Pin n=0..15 */ + +/* Global Interrupt Control High Register */ + +#define IMX9_GPIO_GICHR_GIWD_SHIFT (0) /* Bits 0-15: Global Interrupt Write Data */ +#define IMX9_GPIO_GICHR_GIWD_MASK (0xffff << IMX9_GPIO_GICHR_GIWD_SHIFT) +# define IMX9_GPIO_GICHR_GIWD_PIN(n) ((uint32_t)((n) - 16) << IMX9_GPIO_GICHR_GIWD_SHIFT) /* Pin n=16..31 */ + +#define IMX9_GPIO_GICHR_GIWE_SHIFT (16) /* Bits 16-31: Global Interrupt Write Enable */ +#define IMX9_GPIO_GICHR_GIWE_MASK (0xffff << IMX9_GPIO_GICHR_GIWE_SHIFT) +# define IMX9_GPIO_GICHR_GIWE_PIN(n) ((uint32_t)((n) - 16) << IMX9_GPIO_GICHR_GIWE_SHIFT) /* Pin n=16..31 */ + +/* Interrupt Status Flag Register */ + +#define IMX9_GPIO_ISFR(n) (1 << (n)) /* Interrupt Status Flag, n=0-31 */ + +#endif /* __ARCH_ARM_SRC_IMX9_HARDWARE_IMX9_GPIO_H */ diff --git a/arch/arm64/src/imx9/hardware/imx9_iomuxc.h b/arch/arm64/src/imx9/hardware/imx9_iomuxc.h new file mode 100644 index 0000000000000..6e6fe9979c509 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_iomuxc.h @@ -0,0 +1,104 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_iomuxc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_IOMUXC_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_IOMUXC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_ARCH_CHIP_IMX93) +# include "hardware/imx93/imx93_iomux.h" +#else +# error Unrecognized i.MX9 architecture +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Pad muxing */ + +#define IOMUXC_MUX_MODE_SHIFT (0) /* MODE: pin alternate function */ +#define IOMUXC_MUX_MODE_MASK (0x03 << IOMUXC_MUX_MODE_SHIFT) +#define IOMUXC_MUX_MODE_ALT0 (0 << IOMUXC_MUX_MODE_SHIFT) +#define IOMUXC_MUX_MODE_ALT1 (1 << IOMUXC_MUX_MODE_SHIFT) +#define IOMUXC_MUX_MODE_ALT2 (2 << IOMUXC_MUX_MODE_SHIFT) +#define IOMUXC_MUX_MODE_ALT3 (3 << IOMUXC_MUX_MODE_SHIFT) +#define IOMUXC_MUX_MODE_ALT4 (4 << IOMUXC_MUX_MODE_SHIFT) +#define IOMUXC_MUX_MODE_ALT5 (5 << IOMUXC_MUX_MODE_SHIFT) +#define IOMUXC_MUX_MODE_ALT6 (6 << IOMUXC_MUX_MODE_SHIFT) + +#define IOMUXC_MUX_SION_SHIFT (4) /* SION: Force input path */ +#define IPMUXC_MUX_SION_MASK (0x01 << IOMUXC_MUX_SION_SHIFT) +#define IOMUXC_MUX_SION_OFF (0 << IOMUXC_MUX_SION_SHIFT) +#define IOMUXC_MUX_SION_ON (1 << IOMUXC_MUX_SION_SHIFT) + +/* Pad control */ + +#define IOMUXC_PAD_DSE_SHIFT (1) /* DSE: Drive strength */ +#define IOMUXC_PAD_DSE_MASK (0x3f << IOMUXC_PAD_DSE_SHIFT) +#define IOMUXC_PAD_DSE_X0 (0x00 << IOMUXC_PAD_DSE_SHIFT) +#define IOMUXC_PAD_DSE_X1 (0x01 << IOMUXC_PAD_DSE_SHIFT) +#define IOMUXC_PAD_DSE_X2 (0x03 << IOMUXC_PAD_DSE_SHIFT) +#define IOMUXC_PAD_DSE_X3 (0x07 << IOMUXC_PAD_DSE_SHIFT) +#define IOMUXC_PAD_DSE_X4 (0x0f << IOMUXC_PAD_DSE_SHIFT) +#define IOMUXC_PAD_DSE_X5 (0x1f << IOMUXC_PAD_DSE_SHIFT) +#define IOMUXC_PAD_DSE_X6 (0x3f << IOMUXC_PAD_DSE_SHIFT) + +#define IOMUXC_PAD_FSEL_SHIFT (7) /* FSEL: Slew rate control */ +#define IOMUXC_PAD_FSEL_MASK (0x02 << IOMUXC_PAD_FSEL_SHIFT) +#define IOMUXC_PAD_FSEL_SLOW (0 << IOMUXC_PAD_FSEL_SHIFT) +#define IOMUXC_PAD_FSEL_SSLOW (1 << IOMUXC_PAD_FSEL_SHIFT) /* Slightly slow */ +#define IOMUXC_PAD_FSEL_SFAST (2 << IOMUXC_PAD_FSEL_SHIFT) /* Slightly fast */ +#define IOMUXC_PAD_FSEL_FAST (3 << IOMUXC_PAD_FSEL_SHIFT) + +#define IOMUXC_PAD_PU_SHIFT (9) /* PU: Pull-up */ +#define IOMUXC_PAD_PU_MASK (0x01 << IOMUXC_PAD_PU_SHIFT) +#define IOMUXC_PAD_PU_OFF (0 << IOMUXC_PAD_PU_SHIFT) +#define IOMUXC_PAD_PU_ON (1 << IOMUXC_PAD_PU_SHIFT) + +#define IOMUXC_PAD_PD_SHIFT (10) /* PD: Pull-down */ +#define IOMUXC_PAD_PD_MASK (0x01 << IOMUXC_PAD_PD_SHIFT) +#define IOMUXC_PAD_PD_OFF (0 << IOMUXC_PAD_PD_SHIFT) +#define IOMUXC_PAD_PD_ON (1 << IOMUXC_PAD_PD_SHIFT) + +#define IOMUXC_PAD_OD_SHIFT (11) /* OD: Open-drain */ +#define IOMUXC_PAD_OD_MASK (0x01 << IOMUXC_PAD_OD_SHIFT) +#define IOMUXC_PAD_OD_DISABE (0 << IOMUXC_PAD_OD_SHIFT) +#define IOMUXC_PAD_OD_ENABLE (1 << IOMUXC_PAD_OD_SHIFT) + +#define IOMUXC_PAD_HYS_SHIFT (12) /* HYS: Enable schmitt-trigger on input */ +#define IOMUXC_PAD_HYS_MASK (0x01 << IOMUXC_PAD_HYS_SHIFT) +#define IOMUXC_PAD_HYS_ST_OFF (0 << IOMUXC_PAD_HYS_SHIFT) /* Schmitt-trigger off */ +#define IOMUXC_PAD_HYS_ST_ON (1 << IOMUXC_PAD_HYS_SHIFT) /* Schmitt-trigger on */ + +#define IOMUXC_PAD_APC_SHIFT (24) /* APC: Access control */ +#define IOMUXC_PAD_APC_MASK (0xff << IOMUXC_PAD_APC_SHIFT) + +/* Daisy chain control, 2 bits seems to be enough */ + +#define IOMUXC_DSY_SHIFT (0) +#define IOMUXC_DSY_MASK (0x03 << IOMUXC_DSY_SHIFT) + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_IOMUXC_H */ diff --git a/arch/arm64/src/imx9/hardware/imx9_lpit.h b/arch/arm64/src/imx9/hardware/imx9_lpit.h new file mode 100644 index 0000000000000..5d1d32b494396 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_lpit.h @@ -0,0 +1,125 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_lpit.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPIT_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPIT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define IMX9_LPIT_VERID_OFFSET 0x0000 /* Version ID */ +#define IMX9_LPIT_PARAM_OFFSET 0x0004 /* Parameter */ +#define IMX9_LPIT_MCR_OFFSET 0x0008 /* Module Control */ +#define IMX9_LPIT_MSR_OFFSET 0x000c /* Module Status Register */ +#define IMX9_LPIT_MIER_OFFSET 0x0010 /* Moduel Interrupt Enable */ +#define IMX9_LPIT_SETTEN_OFFSET 0x0014 /* Set Timer Enable */ +#define IMX9_LPIT_CLRTEN_OFFSET 0x0018 /* Clear Timer Enable */ +#define IMX9_LPIT_TVAL0_OFFSET 0x0020 /* Timer Channel 0 Value */ +#define IMX9_LPIT_CVAL0_OFFSET 0x0024 /* Current Timer Channel 0 Value */ +#define IMX9_LPIT_TCTRL0_OFFSET 0x0028 /* Timer Channel 0 Control */ +#define IMX9_LPIT_TVAL1_OFFSET 0x0030 /* Timer Channel 1 Value */ +#define IMX9_LPIT_CVAL1_OFFSET 0x0034 /* Current Timer Channel 1 Value */ +#define IMX9_LPIT_TCTRL1_OFFSET 0x0048 /* Timer Channel 1 Control */ +#define IMX9_LPIT_TVAL2_OFFSET 0x0040 /* Timer Channel 2 Value */ +#define IMX9_LPIT_CVAL2_OFFSET 0x0044 /* Current Timer Channel 2 Value */ +#define IMX9_LPIT_TCTRL2_OFFSET 0x0048 /* Timer Channel 2 Control */ +#define IMX9_LPIT_TVAL3_OFFSET 0x0050 /* Timer Channel 3 Value */ +#define IMX9_LPIT_CVAL3_OFFSET 0x0054 /* Current Timer Channel 3 Value */ +#define IMX9_LPIT_TCTRL3_OFFSET 0x0058 /* Timer Channel 3 Control */ + +/* Register access */ + +#define LPIT_VERID(n) ((n) + IMX9_LPIT_VERID_OFFSET) +#define LPIT_PARAM(n) ((n) + IMX9_LPIT_PARAM_OFFSET) +#define LPIT_MCR(n) ((n) + IMX9_LPIT_MCR_OFFSET) +#define LPIT_MSR(n) ((n) + IMX9_LPIT_MSR_OFFSET) +#define LPIT_MIER(n) ((n) + IMX9_LPIT_MIER_OFFSET) +#define LPIT_SETTEN(n) ((n) + IMX9_LPIT_SETTEN_OFFSET) +#define LPIT_CLRTEN(n) ((n) + IMX9_LPIT_CLRTEN_OFFSET) +#define LPIT_TVAL0(n) ((n) + IMX9_LPIT_TVAL0_OFFSET) +#define LPIT_CVAL0(n) ((n) + IMX9_LPIT_CVAL0_OFFSET) +#define LPIT_TCTRL0(n) ((n) + IMX9_LPIT_TCTRL0_OFFSET) +#define LPIT_TVAL1(n) ((n) + IMX9_LPIT_TVAL1_OFFSET) +#define LPIT_CVAL1(n) ((n) + IMX9_LPIT_CVAL1_OFFSET) +#define LPIT_TCTRL1(n) ((n) + IMX9_LPIT_TCTRL1_OFFSET) +#define LPIT_TVAL2(n) ((n) + IMX9_LPIT_TVAL2_OFFSET) +#define LPIT_CVAL2(n) ((n) + IMX9_LPIT_CVAL2_OFFSET) +#define LPIT_TCTRL2(n) ((n) + IMX9_LPIT_TCTRL2_OFFSET) +#define LPIT_TVAL3(n) ((n) + IMX9_LPIT_TVAL3_OFFSET) +#define LPIT_CVAL3(n) ((n) + IMX9_LPIT_CVAL3_OFFSET) +#define LPIT_TCTRL3(n) ((n) + IMX9_LPIT_TCTRL3_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +#define LPIT_PARAM_EXT_TRIG_SHIFT (8) /* Bit[15:8]: Number of External Trigger Inputs */ +#define LPIT_PARAM_EXT_TRIG_MASK (0xff << LPIT_PARAM_EXT_TRIG_SHIFT) + +#define LPIT_PARAM_CHANNEL_SHIFT (0) /* Bit[7:0]: Number of Timer Channels */ +#define LPIT_PARAM_CHANNEL_MASK (0xff << LPIT_PARAM_CHANNEL_SHIFT) + +#define LPIT_MCR_DBG_EN (1 << 3) /* Stop Timer when in Debug Mode */ +#define LPIT_MCR_DOZE_EN (1 << 2) /* DOZE Mode Enable */ +#define LPIT_MCR_SW_RST (1 << 1) /* Software Reset Bit */ +#define LPIT_MCR_M_CEN (1 << 0) /* Module Clock Enable */ + +#define LPIT_MSR_TIF3 (1 << 3) /* Channel 3 Timer Interrupt Flag */ +#define LPIT_MSR_TIF2 (1 << 2) /* Channel 2 Timer Interrupt Flag */ +#define LPIT_MSR_TIF1 (1 << 1) /* Channel 1 Timer Interrupt Flag */ +#define LPIT_MSR_TIF0 (1 << 0) /* Channel 0 Timer Interrupt Flag */ + +#define LPIT_MIER_TIE3 (1 << 3) /* Channel 3 Timer Interrupt Enable */ +#define LPIT_MIER_TIE2 (1 << 2) /* Channel 2 Timer Interrupt Enable */ +#define LPIT_MIER_TIE1 (1 << 1) /* Channel 1 Timer Interrupt Enable */ +#define LPIT_MIER_TIE0 (1 << 0) /* Channel 0 Timer Interrupt Enable */ + +#define LPIT_TCTRL_TRG_SEL_SHIFT (27) /* Bit[27:24]: Trigger Select */ +#define LPIT_TCTRL_TRG_SEL_MASK (0xf << LPIT_TCTRL_TRG_SEL_SHIFT) +#define LPIT_TCTRL_TRG_SEL_CHAN0 (0 << LPIT_TCTRL_TRG_SEL_SHIFT) +#define LPIT_TCTRL_TRG_SEL_CHAN1 (1 << LPIT_TCTRL_TRG_SEL_SHIFT) +#define LPIT_TCTRL_TRG_SEL_CHAN2 (2 << LPIT_TCTRL_TRG_SEL_SHIFT) +#define LPIT_TCTRL_TRG_SEL_CHAN3 (3 << LPIT_TCTRL_TRG_SEL_SHIFT) + +#define LPIT_TCTRL_TRG_SRC_SHIFT (23) /* Bit23: Trigger Source */ +#define LPIT_TCTRL_TRG_SRC_MASK (1 << LPIT_TCTRL_TRG_SRC_SHIFT) +#define LPIT_TCTRL_TRG_SRC_EXTER (0 << LPIT_TCTRL_TRG_SRC_SHIFT) /* external */ +#define LPIT_TCTRL_TRG_SRC_INTER (1 << LPIT_TCTRL_TRG_SRC_SHIFT) /* internal */ + +#define LPIT_TCTRL_TROT (1 << 18) /* Timer Reload On Trigger */ +#define LPIT_TCTRL_TSOI (1 << 17) /* Timer Stop On Interrupt */ +#define LPIT_TCTRL_TSOT (1 << 16) /* Timer Start On Trigger */ + +#define LPIT_TCTRL_MODE_SHIFT (2) +#define LPIT_TCTRL_MODE_MASK (3 << LPIT_TCTRL_MODE_SHIFT) +#define LPIT_TCTRL_MODE_32PC (0 << LPIT_TCTRL_MODE_SHIFT) /* 32 Bit periodic Counter */ +#define LPIT_TCTRL_MODE_D16PC (1 << LPIT_TCTRL_MODE_SHIFT) /* Dual 16-bit periodic Counter */ +#define LPIT_TCTRL_MODE_32TA (2 << LPIT_TCTRL_MODE_SHIFT) /* 32 bit Trigger Accumulator */ +#define LPIT_TCTRL_MODE_32TIC (3 << LPIT_TCTRL_MODE_SHIFT) /* 32 bit Trigger Input Capture */ + +#define LPIT_TCTRL_CHAIN (1 << 1) /* Chain Channel */ +#define LPIT_TCTRL_T_EN (1 << 0) /* Timer Enable */ + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPIT_H */ diff --git a/arch/arm64/src/imx9/hardware/imx9_lptmr.h b/arch/arm64/src/imx9/hardware/imx9_lptmr.h new file mode 100644 index 0000000000000..73efc0d5a6961 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_lptmr.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_lptmr.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPTMR_H_ +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPTMR_H_ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define IMX9_LPTMR_CSR_OFFSET 0x0000 /* Control Status */ +#define IMX9_LPTMR_PSR_OFFSET 0x0004 /* Prescale */ +#define IMX9_LPTMR_CMR_OFFSET 0x0008 /* Compare */ +#define IMX9_LPTMR_CNR_OFFSET 0x000c /* Counter */ + +/* Register Address *********************************************************/ + +#define LPTMR_CSR(n) ((n) + IMX9_LPTMR_CSR_OFFSET) +#define LPTMR_PSR(n) ((n) + IMX9_LPTMR_PSR_OFFSET) +#define LPTMR_CMR(n) ((n) + IMX9_LPTMR_CMR_OFFSET) +#define LPTMR_CNR(n) ((n) + IMX9_LPTMR_CNR_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +#define LPTMR_CSR_TDRE (1 << 8) /* Timer DMA Request Enable */ +#define LPTMR_CSR_TCF (1 << 7) /* Timer Compare Flag */ +#define LPTMR_CSR_TIE (1 << 6) /* Timer Interrupt Enable */ + +#define LPTMR_CSR_TPS_SHIFT (4) /* Bit[5:4]: Timer Pin Select */ +#define LPTMR_CSR_TPS_MASK (3 << LPTMR_CSR_TPS_SHIFT) +#define LPTMR_CSR_TPS0 (0 << LPTMR_CSR_TPS_SHIFT) +#define LPTMR_CSR_TPS1 (1 << LPTMR_CSR_TPS_SHIFT) +#define LPTMR_CSR_TPS2 (2 << LPTMR_CSR_TPS_SHIFT) +#define LPTMR_CSR_TPS3 (3 << LPTMR_CSR_TPS_SHIFT) + +#define LPTMR_CSR_TPP (1 << 3) /* Timer Pin Polarity */ +#define LPTMR_CSR_TFC (1 << 2) /* Timer Free-Running Counter */ +#define LPTMR_CSR_TMS (1 << 1) /* Timer Mode Select */ +#define LPTMR_CSR_TEN (1 << 0) /* Timer Enable */ + +#define LPTMR_PSR_PRESCALE_SHIFT (3) /* Bit[6:3]: Prescale Value */ +#define LPTMR_PSR_PRESCALE_MASK (0xf << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV2 (0 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV4 (1 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV8 (2 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV16 (3 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV32 (4 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV64 (5 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV128 (6 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV256 (7 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV512 (8 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV1024 (9 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV2048 (10 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV4096 (11 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV8192 (12 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV16384 (13 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV32768 (14 << LPTMR_PSR_PRESCALE_SHIFT) +#define LPTMR_PSR_PRESCALE_DIV65536 (15 << LPTMR_PSR_PRESCALE_SHIFT) + +#define LPTMR_PSR_PBYP (1 << 2) /* Prescaler Bypass */ + +/* Clock sources (module clock / root clock) + * ipg_clk_irclk -> lptmrx_clk_root + * ipg_clk_1khz -> 32k_clk_root + * ipg_clk_32khz -> 32k_clk_root + * ipg_clk_ercl -> 32k_clk_root + */ + +#define LPTMR_PSR_PCS_SHIFT (0) /* Bit[1:0]: Prescaler Clock Select */ +#define LPTMR_PSR_PCS_MASK (3 << LPTMR_PSR_PCS_SHIFT) +#define LPTMR_PSR_PCS_REF_INT (0 << LPTMR_PSR_PCS_SHIFT) /* Internal reference clock */ +#define LPTMR_PSR_PCS_LPO (1 << LPTMR_PSR_PCS_SHIFT) /* LPO 1K Hz */ +#define LPTMR_PSR_PCS_RTC (2 << LPTMR_PSR_PCS_SHIFT) /* RTC 32768 Hz */ +#define LPTMR_PSR_PCS_REF_EXT (3 << LPTMR_PSR_PCS_SHIFT) /* External reference clock */ +# define LPTMR_PSR_PCS_SOSC LPTMR_PSR_PCS_RFOSC + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPTMR_H_ */ diff --git a/arch/arm64/src/imx9/hardware/imx9_lpuart.h b/arch/arm64/src/imx9/hardware/imx9_lpuart.h new file mode 100644 index 0000000000000..3925c51bc606f --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_lpuart.h @@ -0,0 +1,158 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_lpuart.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPUART_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPUART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* 32-bit register definition */ + +#define UARTVERID 0x0000 /* Version ID Register */ +#define UARTPARAM 0x0004 /* Parameter Register */ +#define UARTGLOBAL 0x0008 /* LPUART Global Register */ +#define UARTPINCFG 0x000c /* LPUART Pin Configuration Register */ +#define UARTBAUD 0x0010 /* LPUART Baud Rate Register */ +#define UARTSTAT 0x0014 /* LPUART Status Register */ +#define UARTCTRL 0x0018 /* LPUART Control Register */ +#define UARTDATA 0x001c /* LPUART Data Register */ +#define UARTMATCH 0x0020 /* LPUART Match Address Register */ +#define UARTMODIR 0x0024 /* LPUART Modem IrDA Register */ +#define UARTFIFO 0x0028 /* LPUART FIFO Register */ +#define UARTWATER 0x002c /* LPUART Watermark Register */ + +#define UARTBAUD_MAEN1 0x80000000 +#define UARTBAUD_MAEN2 0x40000000 +#define UARTBAUD_M10 0x20000000 +#define UARTBAUD_TDMAE 0x00800000 +#define UARTBAUD_RDMAE 0x00200000 +#define UARTBAUD_RIDMAE 0x00100000 +#define UARTBAUD_MATCFG 0x00400000 +#define UARTBAUD_BOTHEDGE 0x00020000 +#define UARTBAUD_RESYNCDIS 0x00010000 +#define UARTBAUD_LBKDIE 0x00008000 +#define UARTBAUD_RXEDGIE 0x00004000 +#define UARTBAUD_SBNS 0x00002000 +#define UARTBAUD_SBR 0x00000000 +#define UARTBAUD_SBR_MASK 0x1fff +#define UARTBAUD_OSR_MASK 0x1f +#define UARTBAUD_OSR_SHIFT 24 + +#define UARTSTAT_LBKDIF 0x80000000 +#define UARTSTAT_RXEDGIF 0x40000000 +#define UARTSTAT_MSBF 0x20000000 +#define UARTSTAT_RXINV 0x10000000 +#define UARTSTAT_RWUID 0x08000000 +#define UARTSTAT_BRK13 0x04000000 +#define UARTSTAT_LBKDE 0x02000000 +#define UARTSTAT_RAF 0x01000000 +#define UARTSTAT_TDRE 0x00800000 +#define UARTSTAT_TC 0x00400000 +#define UARTSTAT_RDRF 0x00200000 +#define UARTSTAT_IDLE 0x00100000 +#define UARTSTAT_OR 0x00080000 +#define UARTSTAT_NF 0x00040000 +#define UARTSTAT_FE 0x00020000 +#define UARTSTAT_PE 0x00010000 +#define UARTSTAT_MA1F 0x00008000 +#define UARTSTAT_M21F 0x00004000 + +#define UARTCTRL_R8T9 0x80000000 +#define UARTCTRL_R9T8 0x40000000 +#define UARTCTRL_TXDIR 0x20000000 +#define UARTCTRL_TXINV 0x10000000 +#define UARTCTRL_ORIE 0x08000000 +#define UARTCTRL_NEIE 0x04000000 +#define UARTCTRL_FEIE 0x02000000 +#define UARTCTRL_PEIE 0x01000000 +#define UARTCTRL_TIE 0x00800000 +#define UARTCTRL_TCIE 0x00400000 +#define UARTCTRL_RIE 0x00200000 +#define UARTCTRL_ILIE 0x00100000 +#define UARTCTRL_TE 0x00080000 +#define UARTCTRL_RE 0x00040000 +#define UARTCTRL_RWU 0x00020000 +#define UARTCTRL_SBK 0x00010000 +#define UARTCTRL_MA1IE 0x00008000 +#define UARTCTRL_MA2IE 0x00004000 +#define UARTCTRL_IDLECFG_OFF 0x8 +#define UARTCTRL_LOOPS 0x00000080 +#define UARTCTRL_DOZEEN 0x00000040 +#define UARTCTRL_RSRC 0x00000020 +#define UARTCTRL_M 0x00000010 +#define UARTCTRL_WAKE 0x00000008 +#define UARTCTRL_ILT 0x00000004 +#define UARTCTRL_PE 0x00000002 +#define UARTCTRL_PT 0x00000001 + +#define UARTDATA_NOISY 0x00008000 +#define UARTDATA_PARITYE 0x00004000 +#define UARTDATA_FRETSC 0x00002000 +#define UARTDATA_RXEMPT 0x00001000 +#define UARTDATA_IDLINE 0x00000800 +#define UARTDATA_MASK 0x3ff + +#define UARTMODIR_IREN 0x00020000 +#define UARTMODIR_RTSWATER_S 0x8 +#define UARTMODIR_TXCTSSRC 0x00000020 +#define UARTMODIR_TXCTSC 0x00000010 +#define UARTMODIR_RXRTSE 0x00000008 +#define UARTMODIR_TXRTSPOL 0x00000004 +#define UARTMODIR_TXRTSE 0x00000002 +#define UARTMODIR_TXCTSE 0x00000001 + +#define UARTFIFO_TXEMPT 0x00800000 +#define UARTFIFO_RXEMPT 0x00400000 +#define UARTFIFO_TXOF 0x00020000 +#define UARTFIFO_RXUF 0x00010000 +#define UARTFIFO_TXFLUSH 0x00008000 +#define UARTFIFO_RXFLUSH 0x00004000 +#define UARTFIFO_RXIDEN_MASK 0x7 +#define UARTFIFO_RXIDEN_OFF 10 +#define UARTFIFO_TXOFE 0x00000200 +#define UARTFIFO_RXUFE 0x00000100 +#define UARTFIFO_TXFE 0x00000080 +#define UARTFIFO_FIFOSIZE_MASK 0x7 +#define UARTFIFO_TXSIZE_OFF 4 +#define UARTFIFO_RXFE 0x00000008 +#define UARTFIFO_RXSIZE_OFF 0 +#define UARTFIFO_DEPTH(x) (0x1 << ((x) ? ((x) + 1) : 0)) + +#define UARTWATER_COUNT_MASK 0xff +#define UARTWATER_TXCNT_OFF 8 +#define UARTWATER_RXCNT_OFF 24 +#define UARTWATER_WATER_MASK 0xff +#define UARTWATER_TXWATER_OFF 0 +#define UARTWATER_RXWATER_OFF 16 + +#define UARTGLOBAL_RST 0x2 + +#define UARTFIFO_RXIDEN_RDRF 0x3 +#define UARTCTRL_IDLECFG 0x7 + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPUART_H */ diff --git a/arch/arm64/src/imx9/hardware/imx9_memorymap.h b/arch/arm64/src/imx9/hardware/imx9_memorymap.h new file mode 100644 index 0000000000000..cf682d25a211b --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_memorymap.h @@ -0,0 +1,36 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_IMX9_HARDWARE_IMX9_MEMORYMAP_H +#define __ARCH_ARM_SRC_IMX9_HARDWARE_IMX9_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_ARCH_CHIP_IMX93) +# include "hardware/imx93/imx93_memorymap.h" +#else +# error Unrecognized i.MX9 architecture +#endif + +#endif /* __ARCH_ARM_SRC_IMX9_HARDWARE_IMX9_MEMORYMAP_H */ diff --git a/arch/arm64/src/imx9/hardware/imx9_pinmux.h b/arch/arm64/src/imx9/hardware/imx9_pinmux.h new file mode 100644 index 0000000000000..689485dff6db7 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_pinmux.h @@ -0,0 +1,36 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_pinmux.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_PINMUX_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_PINMUX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#if defined(CONFIG_ARCH_CHIP_IMX93) +# include "hardware/imx93/imx93_pinmux.h" +#else +# error Unrecognized i.MX9 architecture +#endif + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_PINMUX_H */ diff --git a/arch/arm64/src/imx9/hardware/imx9_tpm.h b/arch/arm64/src/imx9/hardware/imx9_tpm.h new file mode 100644 index 0000000000000..0b6c3b5dc84eb --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_tpm.h @@ -0,0 +1,206 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_tpm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_TPM_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_TPM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define IMX9_TPM_VERID_OFFSET 0x0000 /* Version ID */ +#define IMX9_TPM_PARAM_OFFSET 0x0004 /* Parameter */ +#define IMX9_TPM_GLOBAL_OFFSET 0x0008 /* TPM Global */ +#define IMX9_TPM_SC_OFFSET 0x0010 /* Status and Control */ +#define IMX9_TPM_CNT_OFFSET 0x0014 /* Counter */ +#define IMX9_TPM_MOD_OFFSET 0x0018 /* Modulo */ +#define IMX9_TPM_STATUS_OFFSET 0x001c /* Capture and Compare Status */ +#define IMX9_TPM_CXSC_OFFSET(ch) (0x0020 + (ch) * 8) /* Channel Status and Control */ +#define IMX9_TPM_CXV_OFFSET(ch) (0x0024 + (ch) * 8) /* Channel Value */ +#define IMX9_TPM_C1SC_OFFSET 0x0028 /* Channel n Status and Control */ +#define IMX9_TPM_C1V_OFFSET 0x002c /* Channel n Value */ +#define IMX9_TPM_C2SC_OFFSET 0x0030 /* Channel n Status and Control */ +#define IMX9_TPM_C2V_OFFSET 0x0034 /* Channel n Value */ +#define IMX9_TPM_C3SC_OFFSET 0x0038 /* Channel n Status and Control */ +#define IMX9_TPM_C3V_OFFSET 0x003c /* Channel n Value */ +#define IMX9_TPM_COMBINE_OFFSET 0x0064 /* Combine Channel */ +#define IMX9_TPM_TRIG_OFFSET 0x006c /* Channel Trigger */ +#define IMX9_TPM_POL_OFFSET 0x0070 /* Channel Polarity */ +#define IMX9_TPM_FILTER_OFFSET 0x0078 /* Filter Control */ +#define IMX9_TPM_QDCTRL_OFFSET 0x0080 /* Quadrature Decoder Control and Status */ +#define IMX9_TPM_CONF_OFFSET 0x0084 /* Configuration */ + +/* Register Bitfield Definitions ********************************************/ + +/* PARAM */ + +#define TPM_PARAM_WIDTH_SHIFT (16) /* Bit[23:16]: Width of the counter and timer channels */ +#define TPM_PARAM_WIDTH_MASK (0xff << TPM_PARAM_WIDTH_SHIFT) + +#define TPM_PARAM_TRIG_SHIFT (8) /* Bit[15:8]: Number of triggers that TPM implements */ +#define TPM_PARAM_TRIG_MASK (0xff << LPIT_PARAM_TRIG_SHIFT) + +#define TPM_PARAM_CHAN_SHIFT (0) /* Bit[7:0]: Number of timer channels */ +#define TPM_PARAM_CHAN_MASK (0xff << TPM_PARAM_CHAN_SHIFT) + +/* GLOBAL */ + +#define TPM_GLOBAL_RST_SHIFT (1) /* Bit[1]: Software Reset */ +#define TPM_GLOBAL_RST_MASK (0x1 << TPM_GLOBAL_RST_SHIFT) + +#define TPM_GLOBAL_NOUPDATE_SHIFT (0) /* Bit[0]: Block updates to internal registers */ +#define TPM_GLOBAL_NOUPDATE_MASK (0x1 << TPM_GLOBAL_NOUPDATE_SHIFT) + +/* SC */ + +#define TPM_SC_DMA_SHIFT (8) /* Bit[8]: DMA Enable */ +#define TPM_SC_DMA_MASK (0x1 << TPM_SC_DMA_SHIFT) + +#define TPM_SC_TOF_SHIFT (7) /* Bit[7]: Timer Overflow Flag */ +#define TPM_SC_TOF_MASK (0x1 << TPM_SC_TOF_SHIFT) + +#define TPM_SC_TOIE_SHIFT (6) /* Bit[6]: Timer Overflow Interrupt Enable */ +#define TPM_SC_TOIE_MASK (0x1 << TPM_SC_TOIE_SHIFT) + +#define TPM_SC_CPWMS_SHIFT (5) /* Bit[5]: Center-Aligned PWM Select */ +#define TPM_SC_CPWMS_MASK (0x1 << TPM_SC_CPWMS_SHIFT) + +#define TPM_SC_CMOD_SHIFT (3) /* Bit[4:3]: Clock Mode Selection */ +#define TPM_SC_CMOD_MASK (0x3 << TPM_SC_CMOD_SHIFT) + +#define TPM_SC_PS_SHIFT (0) /* Bit[2:0]: Prescale Factor Selection */ +#define TPM_SC_PS_MASK (0x7 << TPM_SC_PS_SHIFT) + +/* STATUS */ + +#define TPM_STATUS_TOF_SHIFT (8) /* Bit[8]: Timer Overflow Flag */ +#define TPM_STATUS_TOF_MASK (0x1 << TPM_STATUS_TOF_SHIFT) + +#define TPM_STATUS_CH3F_SHIFT (3) /* Bit[3]: Channel 3 Flag */ +#define TPM_STATUS_CH3F_MASK (0x1 << TPM_STATUS_CH3F_SHIFT) + +#define TPM_STATUS_CH2F_SHIFT (2) /* Bit[2]: Channel 2 Flag */ +#define TPM_STATUS_CH2F_MASK (0x1 << TPM_STATUS_CH2F_SHIFT) + +#define TPM_STATUS_CH1F_SHIFT (1) /* Bit[1]: Channel 1 Flag */ +#define TPM_STATUS_CH1F_MASK (0x1 << TPM_STATUS_CH1F_SHIFT) + +#define TPM_STATUS_CH0F_SHIFT (0) /* Bit[0]: Channel 0 Flag */ +#define TPM_STATUS_CH0F_MASK (0x1 << TPM_STATUS_CH0F_SHIFT) + +/* C0SC - C3SC */ + +#define TPM_CXSC_CHF_SHIFT (7) /* Bit[7]: Channel Flag */ +#define TPM_CXSC_CHF_MASK (0x1 << TPM_CXSC_CHF_SHIFT) + +#define TPM_CXSC_CHIE_SHIFT (6) /* Bit[6]: Channel Interrupt Enable */ +#define TPM_CXSC_CHIE_MASK (0x1 << TPM_CXSC_CHIE_SHIFT) + +#define TPM_CXSC_MSB_SHIFT (5) /* Bit[5]: Channel Mode Select B */ +#define TPM_CXSC_MSB_MASK (0x1 << TPM_CXSC_MSB_SHIFT) + +#define TPM_CXSC_MSA_SHIFT (4) /* Bit[4]: Channel Mode Select A */ +#define TPM_CXSC_MSA_MASK (0x1 << TPM_CXSC_MSA_SHIFT) + +#define TPM_CXSC_ELSB_SHIFT (3) /* Bit[3]: Edge or Level Select B */ +#define TPM_CXSC_ELSB_MASK (0x1 << TPM_CXSC_ELSB_SHIFT) + +#define TPM_CXSC_ELSA_SHIFT (2) /* Bit[2]: Edge or Level Select A */ +#define TPM_CXSC_ELSA_MASK (0x1 << TPM_CXSC_ELSA_SHIFT) + +#define TPM_CXSC_DMA_SHIFT (0) /* Bit[0]: DMA Enable */ +#define TPM_CXSC_DMA_MASK (0x1 << TPM_CXSC_DMA_SHIFT) + +/* COMBINE */ + +#define TPM_COMBINE_COMSWAP1_SHIFT (9) /* Bit[9]: Combine Channels 2 and 3 Swap */ +#define TPM_COMBINE_COMSWAP1_MASK (0x1 << TPM_COMBINE_COMSWAP1_SHIFT) + +#define TPM_COMBINE_COMBINE1_SHIFT (8) /* Bit[8]: Combine Channels 2 and 3 */ +#define TPM_COMBINE_COMBINE1_MASK (0x1 << TPM_COMBINE_COMBINE1_SHIFT) + +#define TPM_COMBINE_COMSWAP0_SHIFT (1) /* Bit[1]: Combine Channel 0 and 1 Swap */ +#define TPM_COMBINE_COMSWAP0_MASK (0x1 << TPM_COMBINE_COMSWAP0_SHIFT) + +#define TPM_COMBINE_COMBINE0_SHIFT (0) /* Bit[0]: Combine Channels 0 and 1 */ +#define TPM_COMBINE_COMBINE0_MASK (0x1 << TPM_COMBINE_COMBINE0_SHIFT) + +/* TRIG */ + +#define TPM_TRIG_TRIGX_MASK(ch) (0x1 << (ch)) /* Channel trigger configure */ + +/* POL */ + +#define TPM_POL_POLX_MASK(ch) (0x1 < (ch)) /* Channel polarity active low */ + +/* FILTER */ + +#define TPM_FILTER_CHXFVAL_MASK(ch) (0xf << ((ch) * 4))) /* Channel filter value */ + +/* QDCTRL */ + +#define TPM_QDCTRL_QUADMODE_SHIFT (3) /* Bit[3]: Quadrature Decoder Mode */ +#define TPM_QDCTRL_QUADMODE_MASK (0x1 << TPM_QDCTRL_QUADMODE_SHIFT) + +#define TPM_QDCTRL_QUADIR_SHIFT (2) /* Bit[2]: Counter Direction */ +#define TPM_QDCTRL_QUADIR_MASK (0x1 << TPM_QDCTRL_QUADIR_SHIFT) + +#define TPM_QDCTRL_TOFDIR_SHIFT (1) /* Bit[1]: Timer Overflow Direction */ +#define TPM_QDCTRL_TOFDIR_MASK (0x1 << TPM_QDCTRL_TOFDIR_SHIFT) + +#define TPM_QDCTRL_QUADEN_SHIFT (0) /* Bit[0]: Quadrature Decoder Enable */ +#define TPM_QDCTRL_QUADEN_MASK (0x1 << TPM_QDCTRL_QUADEN_SHIFT) + +/* CONF */ + +#define TPM_CONF_TRGSEL_SHIFT (24) /* Bit[25:24]: Trigger Select */ +#define TPM_CONF_TRGSEL_MASK (0x3 << TPM_CONF_TRGSEL_SHIFT) + +#define TPM_CONF_TRGSRC_SHIFT (23) /* Bit[23]: Trigger Source select */ +#define TPM_CONF_TRGSRC_MASK (0x1 << TPM_CONF_TRGSRC_SHIFT) + +#define TPM_CONF_TRGPOL_SHIFT (22) /* Bit[22]: Trigger Polarity */ +#define TPM_CONF_TRGPOL_MASK (0x1 << TPM_CONF_TRGPOL_SHIFT) + +#define TPM_CONF_CPOT_SHIFT (19) /* Bit[19]: Counter Pause on Trigger */ +#define TPM_CONF_CPOT_MASK (0x1 << TPM_CONF_CPOT_SHIFT) + +#define TPM_CONF_CROT_SHIFT (18) /* Bit[18]: Counter Reload on Trigger */ +#define TPM_CONF_CROT_MASK (0x1 << TPM_CONF_CROT_SHIFT) + +#define TPM_CONF_CSOO_SHIFT (17) /* Bit[17]: Counter Stop on Overflow */ +#define TPM_CONF_CSOO_MASK (0x1 << TPM_CONF_CSOO_SHIFT) + +#define TPM_CONF_CSOT_SHIFT (16) /* Bit[16]: Counter Start on Trigger */ +#define TPM_CONF_CSOT_MASK (0x1 << TPM_CONF_CSOT_SHIFT) + +#define TPM_CONF_DBGMODE_SHIFT (6) /* Bit[7:6]: Debug Mode */ +#define TPM_CONF_DBGMODE_MASK (0x3 << TPM_CONF_DBGMODE_SHIFT) + +#define TPM_CONF_DOZEEN_SHIFT (5) /* Bit[5]: Doze Enable */ +#define TPM_CONF_DOZEEN_MASK (0x1 << TPM_CONF_DOZEEN_SHIFT) + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_TPM_H */ diff --git a/arch/arm64/src/imx9/hardware/imx9_usbotg.h b/arch/arm64/src/imx9/hardware/imx9_usbotg.h new file mode 100644 index 0000000000000..c59119e8dd9f5 --- /dev/null +++ b/arch/arm64/src/imx9/hardware/imx9_usbotg.h @@ -0,0 +1,665 @@ +/**************************************************************************** + * arch/arm64/src/imx9/hardware/imx9_usbotg.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_USBOTG_H +#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_USBOTG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IMX9_EHCI_NRHPORT 1 + +#define IMX9_USBOTG_ID_OFFSET 0x000 /* Identification */ +#define IMX9_USBHOST_HWGENERAL_OFFSET 0x004 /* Hardware General */ +#define IMX9_USBHOST_HWHOST_OFFSET 0x008 /* Host Hardware Parameters */ +#define IMX9_USBHOST_HWDEVICE_OFFSET 0x00c /* Device Hardware Parameters */ +#define IMX9_USBHOST_HWTXBUF_OFFSET 0x010 /* TX Buffer Hardware Parameters */ +#define IMX9_USBHOST_HWRXBUF_OFFSET 0x014 /* RX Buffer Hardware Parameters */ +#define IMX9_USBHOST_GPTIMER0LD_OFFSET 0x080 /* General Purpose Timer #0 Load */ +#define IMX9_USBHOST_GPTIMER0CTRL_OFFSET 0x084 /* General Purpose Timer #0 Controller */ +#define IMX9_USBHOST_GPTIMER1LD_OFFSET 0x088 /* General Purpose Timer #1 Load */ +#define IMX9_USBHOST_GPTIMER1CTRL_OFFSET 0x08c /* General Purpose Timer #1 Controller */ +#define IMX9_USBHOST_SBUSCFG_OFFSET 0x090 /* System Bus Config */ + +/* Device/host capability registers */ + +#define IMX9_USBOTG_CAPLENGTH_OFFSET 0x100 /* Capability register length (8-bit) */ +#define IMX9_USBHOST_HCIVERSION_OFFSET 0x102 /* Host interface version number (16-bit) */ +#define IMX9_USBHOST_HCSPARAMS_OFFSET 0x104 /* Host controller structural parameters */ +#define IMX9_USBHOST_HCCPARAMS_OFFSET 0x108 /* Host controller capability parameters */ +#define IMX9_USBDEV_DCIVERSION_OFFSET 0x120 /* Device interface version number */ +#define IMX9_USBDEV_DCCPARAMS_OFFSET 0x124 /* Device controller capability parameters */ + +/* Device/host/OTG operational registers */ + +#define IMX9_USBOTG_USBCMD_OFFSET 0x140 /* USB command (both) */ +#define IMX9_USBOTG_USBSTS_OFFSET 0x144 /* USB status (both) */ +#define IMX9_USBOTG_USBINTR_OFFSET 0x148 /* USB interrupt enable (both) */ +#define IMX9_USBOTG_FRINDEX_OFFSET 0x14c /* USB frame index (both) */ +#define IMX9_USBOTG_DEVICEADDR_OFFSET 0x154 /* USB device address (device) */ +#define IMX9_USBOTG_ASYNCLISTADDR_OFFSET 0x158 /* Next asynchronous list address (host) */ +#define IMX9_USBOTG_ENDPOINTLIST_OFFSET 0x158 /* Address of endpoint list in memory (device) */ +#define IMX9_USBOTG_BURSTSIZE_OFFSET 0x160 /* Programmable burst size (both) */ +#define IMX9_USBOTG_TXFILLTUNING_OFFSET 0x164 /* Host transmit pre-buffer packet tuning (host) */ +#define IMX9_USBOTG_ENDPTNAK_OFFSET 0x178 /* Endpoint NAK (device) */ +#define IMX9_USBOTG_ENDPTNAKEN_OFFSET 0x17c /* Endpoint NAK Enable (device) */ +#define IMX9_USBOTG_CONFIGFLAG_OFFSET 0x180 /* Configured flag register (not used in lpc313x) */ +#define IMX9_USBOTG_PORTSC1_OFFSET 0x184 /* Port status/control 1 (both) */ +#define IMX9_USBOTG_OTGSC_OFFSET 0x1a4 /* OTG status and control (otg) */ +#define IMX9_USBOTG_USBMODE_OFFSET 0x1a8 /* USB device mode (both) */ + +#define IMX9_USBDEV_USBCMD_OFFSET 0x140 /* USB command (both) */ +#define IMX9_USBDEV_USBSTS_OFFSET 0x144 /* USB status (both) */ +#define IMX9_USBDEV_USBINTR_OFFSET 0x148 /* USB interrupt enable (both) */ +#define IMX9_USBDEV_FRINDEX_OFFSET 0x14c /* USB frame index (both) */ +#define IMX9_USBDEV_DEVICEADDR_OFFSET 0x154 /* USB device address (device) */ +#define IMX9_USBDEV_ENDPOINTLIST_OFFSET 0x158 /* Address of endpoint list in memory (device) */ +#define IMX9_USBDEV_BURSTSIZE_OFFSET 0x160 /* Programmable burst size (both) */ +#define IMX9_USBDEV_ENDPTNAK_OFFSET 0x178 /* Endpoint NAK (device) */ +#define IMX9_USBDEV_ENDPTNAKEN_OFFSET 0x17c /* Endpoint NAK Enable (device) */ +#define IMX9_USBDEV_PORTSC1_OFFSET 0x184 /* Port status/control 1 (both) */ +#define IMX9_USBDEV_USBMODE_OFFSET 0x1a8 /* USB device mode (both) */ + +#define IMX9_USBHOST_USBCMD_OFFSET 0x140 /* USB command (both) */ +#define IMX9_USBHOST_USBSTS_OFFSET 0x144 /* USB status (both) */ +#define IMX9_USBHOST_USBINTR_OFFSET 0x148 /* USB interrupt enable (both) */ +#define IMX9_USBHOST_FRINDEX_OFFSET 0x14c /* USB frame index (both) */ +#define IMX9_USBHOST_PERIODICLIST_OFFSET 0x154 /* Frame list base address (host) */ +#define IMX9_USBHOST_ASYNCLISTADDR_OFFSET 0x158 /* Next asynchronous list address (host) */ +#define IMX9_USBHOST_TTCTRL_OFFSET 0x15c /* Asynchronous buffer status for embedded TT (host) */ +#define IMX9_USBHOST_BURSTSIZE_OFFSET 0x160 /* Programmable burst size (both) */ +#define IMX9_USBHOST_TXFILLTUNING_OFFSET 0x164 /* Host transmit pre-buffer packet tuning (host) */ +#define IMX9_USBHOST_PORTSC1_OFFSET 0x184 /* Port status/control 1 (both) */ +#define IMX9_USBHOST_USBMODE_OFFSET 0x1a8 /* USB device mode (both) */ + +/* Device endpoint registers */ + +#define IMX9_USBDEV_ENDPTSETUPSTAT_OFFSET 0x1ac /* Endpoint setup status */ +#define IMX9_USBDEV_ENDPTPRIME_OFFSET 0x1b0 /* Endpoint initialization */ +#define IMX9_USBDEV_ENDPTFLUSH_OFFSET 0x1b4 /* Endpoint de-initialization */ +#define IMX9_USBDEV_ENDPTSTATUS_OFFSET 0x1b8 /* Endpoint status */ +#define IMX9_USBDEV_ENDPTCOMPLETE_OFFSET 0x1bc /* Endpoint complete */ + +#define IMX9_USBDEV_ENDPTCTRL_OFFSET(n) (IMX9_USBDEV_ENDPTCTRL0_OFFSET + ((n) * 4)) +#define IMX9_USBDEV_ENDPTCTRL0_OFFSET 0x1c0 /* Endpoint control 0 */ +#define IMX9_USBDEV_ENDPTCTRL1_OFFSET 0x1c4 /* Endpoint control 1 */ +#define IMX9_USBDEV_ENDPTCTRL2_OFFSET 0x1c8 /* Endpoint control 2 */ +#define IMX9_USBDEV_ENDPTCTRL3_OFFSET 0x1cc /* Endpoint control 3 */ +#define IMX9_USBDEV_ENDPTCTRL4_OFFSET 0x1d0 /* Endpoint control 4 */ +#define IMX9_USBDEV_ENDPTCTRL5_OFFSET 0x1d4 /* Endpoint control 5 */ +#define IMX9_USBDEV_ENDPTCTRL6_OFFSET 0x1d8 /* Endpoint control 6 */ +#define IMX9_USBDEV_ENDPTCTRL7_OFFSET 0x1dc /* Endpoint control 7 */ + +/* USB Non-core memory map & register definition */ + +#define IMX9_USBNC_CTRL1_OFFSET 0x0200 /* USB OTG Control Register 1 */ +#define IMX9_USBNC_CTRL2_OFFSET 0x0204 /* USB OTG Control Register 2 */ +#define IMX9_USBNC_UTMIPHY_CFG1_OFFSET 0x0230 /* PHY Configure 1 */ + +/* USBOTG register bit definitions ******************************************/ + +/* Device/host capability registers */ + +/* CAPLENGTH */ + +#define USBOTG_CAPLENGTH_SHIFT (0) /* Bits 0-7: Offset from register base to operational regs */ +#define USBOTG_CAPLENGTH_MASK (0xff << USBOTG_CAPLENGTH_SHIFT) + +/* HCIVERSION */ + +#define USBHOST_HCIVERSION_SHIFT (0) /* Bits 0-15: BCD encoding of the EHCI revision number */ +#define USBHOST_HCIVERSION_MASK (0xffff << USBHOST_HCIVERSION_SHIFT) + +/* HCSPARAMS */ + +#define USBHOST_HCSPARAMS_NTT_SHIFT (24) /* Bits 24-27: Number of Transaction Translators */ +#define USBHOST_HCSPARAMS_NTT_MASK (0xf << USBHOST_HCSPARAMS_NTT_SHIFT) +#define USBHOST_HCSPARAMS_NPTT_SHIFT (20) /* Bits 20-23: Number of Ports per Transaction Translator */ +#define USBHOST_HCSPARAMS_NPTT_MASK (15 << USBHOST_HCSPARAMS_NPTT_SHIFT) +#define USBHOST_HCSPARAMS_PI (1 << 16) /* Bit 16: Port indicators */ +#define USBHOST_HCSPARAMS_NCC_SHIFT (12) /* Bits 12-15: Number of Companion Controller */ +#define USBHOST_HCSPARAMS_NCC_MASK (0xf << USBHOST_HCSPARAMS_NCC_SHIFT) +#define USBHOST_HCSPARAMS_NPCC_SHIFT (8) /* Bits 8-11: Number of Ports per Companion Controller */ +#define USBHOST_HCSPARAMS_NPCC_MASK (0xf << USBHOST_HCSPARAMS_NPCC_SHIFT) +#define USBHOST_HCSPARAMS_PPC (1 << 4) /* Bit 4: Port Power Control */ +#define USBHOST_HCSPARAMS_NPORTS_SHIF (0) /* Bits 0-3: Number of downstream ports */ +#define USBHOST_HCSPARAMS_NPORTS_MASK (0xf << USBHOST_HCSPARAMS_NPORTS_SHIFT) + +/* HCCPARAMS */ + +#define USBHOST_HCCPARAMS_EECP_SHIFT (8) /* Bits 8-15: EHCI Extended Capabilities Pointer */ +#define USBHOST_HCCPARAMS_EECP_MASK (0xff << USBHOST_HCCPARAMS_EECP_SHIFT) +#define USBHOST_HCCPARAMS_IST_SHIFT (4) /* Bits 4-7: Isochronous Scheduling Threshold */ +#define USBHOST_HCCPARAMS_IST_MASK (0xf << USBHOST_HCCPARAMS_IST_SHIFT) +#define USBHOST_HCCPARAMS_ASP (1 << 2) /* Bit 2: Asynchronous Schedule Park Capability */ +#define USBHOST_HCCPARAMS_PFL (1 << 1) /* Bit 1: Programmable Frame List Flag */ +#define USBHOST_HCCPARAMS_ADC (1 << 0) /* Bit 0: 64-bit Addressing Capability */ + +/* DCIVERSION */ + +#define USBDEV_DCIVERSION_SHIFT (0) /* Bits 0-15: BCD encoding of the device interface */ +#define USBDEV_DCIVERSION_MASK (0xffff << USBDEV_DCIVERSION_SHIFT) + +/* DCCPARAMS */ + +#define USBDEV_DCCPARAMS_HC (1 << 8) /* Bit 8: Host Capable */ +#define USBDEV_DCCPARAMS_DC (1 << 7) /* Bit 7: Device Capable */ +#define USBDEV_DCCPARAMS_DEN_SHIFT (0) /* Bits 0-4: DEN Device Endpoint Number */ +#define USBDEV_DCCPARAMS_DEN_MASK (0x1f << USBDEV_DCCPARAMS_DEN_SHIFT) + +/* Device/host operational registers */ + +/* USB Command register USBCMD -- Device Mode */ + +#define USBDEV_USBCMD_ITC_SHIFT (16) /* Bits 16-23: Interrupt threshold control */ +#define USBDEV_USBCMD_ITC_MASK (0xff << USBDEV_USBCMD_ITC_SHIFT) +# define USBDEV_USBCMD_ITCIMME (0 << USBDEV_USBCMD_ITC_SHIFT) /* Immediate (no threshold) */ +# define USBDEV_USBCMD_ITC1UF (1 << USBDEV_USBCMD_ITC_SHIFT) /* 1 micro frame */ +# define USBDEV_USBCMD_ITC2UF (2 << USBDEV_USBCMD_ITC_SHIFT) /* 2 micro frames */ +# define USBDEV_USBCMD_ITC4UF (4 << USBDEV_USBCMD_ITC_SHIFT) /* 4 micro frames */ +# define USBDEV_USBCMD_ITC8UF (8 << USBDEV_USBCMD_ITC_SHIFT) /* 8 micro frames */ +# define USBDEV_USBCMD_ITC16UF (16 << USBDEV_USBCMD_ITC_SHIFT) /* 16 micro frames */ +# define USBDEV_USBCMD_ITC32UF (32 << USBDEV_USBCMD_ITC_SHIFT) /* 32 micro frames */ +# define USBDEV_USBCMD_ITC64UF (64 << USBDEV_USBCMD_ITC_SHIFT) /* 64 micro frames */ + +#define USBDEV_USBCMD_ATDTW (1 << 14) /* Bit 14: Add dTD trip wire */ +#define USBDEV_USBCMD_SUTW (1 << 13) /* Bit 13: Setup trip wire */ +#define USBDEV_USBCMD_RST (1 << 1) /* Bit 1: 1 Controller reset */ +#define USBDEV_USBCMD_RS (1 << 0) /* Bit 0: 0 Run/Stop */ + +/* USB Command register USBCMD -- Host Mode */ + +#define USBHOST_USBCMD_ITC_SHIFT (16) /* Bits 16-13: Interrupt threshold control */ +#define USBHOST_USBCMD_ITC_MASK (0xff << USBHOST_USBCMD_ITC_SHIFT) +# define USBHOST_USBCMD_ITCIMMED (0 << USBHOST_USBCMD_ITC_SHIFT) /* Immediate (no threshold) */ +# define USBHOST_USBCMD_ITC1UF (1 << USBHOST_USBCMD_ITC_SHIFT) /* 1 micro frame */ +# define USBHOST_USBCMD_ITC2UF (2 << USBHOST_USBCMD_ITC_SHIFT) /* 2 micro frames */ +# define USBHOST_USBCMD_ITC4UF (4 << USBHOST_USBCMD_ITC_SHIFT) /* 4 micro frames */ +# define USBHOST_USBCMD_ITC8UF (8 << USBHOST_USBCMD_ITC_SHIFT) /* 8 micro frames */ +# define USBHOST_USBCMD_ITC16UF (16 << USBHOST_USBCMD_ITC_SHIFT) /* 16 micro frames */ +# define USBHOST_USBCMD_ITC32UF (32 << USBHOST_USBCMD_ITC_SHIFT) /* 32 micro frames */ +# define USBHOST_USBCMD_ITC64UF (64 << USBHOST_USBCMD_ITC_SHIFT) /* 64 micro frames */ + +#define USBHOST_USBCMD_FS2 (1 << 15) /* Bit 15: Bit 2 of the Frame List Size bits */ +#define USBHOST_USBCMD_ASPE (1 << 11) /* Bit 11: Asynchronous Schedule Park Mode Enable */ +#define USBHOST_USBCMD_ASP_SHIFT (8) /* Bits 8-9: Asynchronous schedule park mode */ +#define USBHOST_USBCMD_ASP_MASK (0x3 << USBHOST_USBCMD_ASP_SHIFT) +#define USBHOST_USBCMD_IAA (1 << 6) /* Bit 6: Interrupt next asynchronous schedule */ +#define USBHOST_USBCMD_ASE (1 << 5) /* Bit 5: Skips processing asynchronous schedule */ +#define USBHOST_USBCMD_PSE (1 << 4) /* Bit 4: Skips processing periodic schedule */ +#define USBHOST_USBCMD_FS1 (1 << 3) /* Bit 3: Bit 1 of the Frame List Size bits */ +#define USBHOST_USBCMD_FS0 (1 << 2) /* Bit 2: Bit 0 of the Frame List Size bits */ +#define USBHOST_USBCMD_RST (1 << 1) /* Bit 1: Controller reset */ +#define USBHOST_USBCMD_RS (1 << 0) /* Bit 0: Run/Stop */ + +/* USB Status register USBSTS -- Device Mode */ + +#define USBDEV_USBSTS_NAKI (1 << 16) /* Bit 16: NAK interrupt bit */ +#define USBDEV_USBSTS_SLI (1 << 8) /* Bit 8: DCSuspend */ +#define USBDEV_USBSTS_SRI (1 << 7) /* Bit 7: SOF received */ +#define USBDEV_USBSTS_URI (1 << 6) /* Bit 6: USB reset received */ +#define USBDEV_USBSTS_PCI (1 << 2) /* Bit 2: Port change detect */ +#define USBDEV_USBSTS_UEI (1 << 1) /* Bit 1: USB error interrupt */ +#define USBDEV_USBSTS_UI (1 << 0) /* Bit 0: USB interrupt */ + +/* USB Status register USBSTS -- Host Mode */ + +#define USBHOST_USBSTS_UPI (1 << 19) /* Bit 19: USB host periodic interrupt */ +#define USBHOST_USBSTS_UAI (1 << 18) /* Bit 18: USB host asynchronous interrupt */ +#define USBHOST_USBSTS_AS (1 << 15) /* Bit 15: Asynchronous schedule status */ +#define USBHOST_USBSTS_PS (1 << 14) /* Bit 14: Periodic schedule status */ +#define USBHOST_USBSTS_RCL (1 << 13) /* Bit 13: Reclamation */ +#define USBHOST_USBSTS_HCH (1 << 12) /* Bit 12: HCHalted */ +#define USBHOST_USBSTS_SRI (1 << 7) /* Bit 7: SOF received */ +#define USBHOST_USBSTS_AAI (1 << 5) /* Bit 5: Interrupt on async advance */ +#define USBHOST_USBSTS_FRI (1 << 3) /* Bit 3: Frame list roll-over */ +#define USBHOST_USBSTS_PCI (1 << 2) /* Bit 2: Port change detect */ +#define USBHOST_USBSTS_UEI (1 << 1) /* Bit 1: USB error interrupt */ +#define USBHOST_USBSTS_UI (1 << 0) /* Bit 0: USB interrupt */ + +/* USB interrupt register USBINTR -- Device Mode */ + +#define USBDEV_USBINTR_NAKE (1 << 16) /* Bit 16: NAK interrupt enable */ +#define USBDEV_USBINTR_SLE (1 << 8) /* Bit 8: Sleep enable */ +#define USBDEV_USBINTR_SRE (1 << 7) /* Bit 7: SOF received enable */ +#define USBDEV_USBINTR_URE (1 << 6) /* Bit 6: USB reset enable */ +#define USBDEV_USBINTR_PCE (1 << 2) /* Bit 2: Port change detect enable */ +#define USBDEV_USBINTR_UEE (1 << 1) /* Bit 1: USB error interrupt enable */ +#define USBDEV_USBINTR_UE (1 << 0) /* Bit 0: USB interrupt enable */ + +/* USB interrupt register USBINTR (address 0x19000148) -- Host Mode */ + +#define USBHOST_USBINTR_UPIE (1 << 19) /* Bit 19: USB host periodic interrupt enable */ +#define USBHOST_USBINTR_UAIE (1 << 18) /* Bit 18: USB host asynchronous interrupt enable */ +#define USBHOST_USBINTR_SRE (1 << 7) /* Bit 7: SOF timer interrupt enable */ +#define USBHOST_USBINTR_AAE (1 << 5) /* Bit 5: Interrupt on asynchronous advance enable */ +#define USBHOST_USBINTR_FRE (1 << 3) /* Bit 3: Frame list rollover enable */ +#define USBHOST_USBINTR_PCE (1 << 2) /* Bit 2: Port change detect enable */ +#define USBHOST_USBINTR_UEE (1 << 1) /* Bit 1: USB error interrupt enable */ +#define USBHOST_USBINTR_UE (1 << 0) /* Bit 0: USB interrupt enable */ + +/* Frame index register FRINDEX -- Device Mode */ + +#define USBDEV_FRINDEX_LFN_SHIFT (3) /* Bits 3-13: Frame number of last frame transmitted */ +#define USBDEV_FRINDEX_LFN_MASK (0x7ff << USBDEV_FRINDEX_LFN_SHIFT) +#define USBDEV_FRINDEX_CUFN_SHIFT (0) /* Bits 0-2: Current micro frame number */ +#define USBDEV_FRINDEX_CUFN_MASK (7 << USBDEV_FRINDEX_CUFN_SHIFT) + +/* Frame index register FRINDEX -- Host Mode */ + +#define USBHOST_FRINDEX_FLI_SHIFT (3) /* Bits 3-13: Frame list current index */ +#define USBHOST_FRINDEX_FLI_MASK(n) (0x7ff << ((n) + USBHOST_FRINDEX_FLI_SHIFT - 1) +#define USBHOST_FRINDEX_CUFN_SHIFT (0) /* Bits 0-2: Current micro frame number */ +#define USBHOST_FRINDEX_CUFN_MASK (0x7 << USBHOST_FRINDEX_CUFN_SHIFT) + +/* USB Device Address register DEVICEADDR -- Device Mode */ + +#define USBDEV_DEVICEADDR_SHIFT (25) /* Bits 25-31: USBADR USB device address */ +#define USBDEV_DEVICEADDR_MASK (0x7f << USBDEV_DEVICEADDR_SHIFT) +#define USBDEV_DEVICEADDR_USBADRA (1 << 24) /* Bit 24: Device address advance */ + +/* USB Periodic List Base register PERIODICLIST -- Host Mode */ + +#define USBHOST_PERIODICLIST_BASEADR_SHIFT (12) /* Bits 12-31: Base Address (Low) */ +#define USBHOST_PERIODICLIST_BASEADR_MASK (0xfffff << USBHOST_PERIODICLIST_PERBASE_SHIFT) + +/* USB Asynchronous List Address register ASYNCLISTADDR -- Host Mode */ + +#define USBHOST_ASYNCLISTADDR_ASYBASE_SHIFT (5) /* Bits 5-31: Link pointer (Low) LPL */ +#define USBHOST_ASYNCLISTADDR_ASYBASE_MASK (0x07ffffff << USBHOST_ASYNCLISTADDR_ASYBASE_SHIFT) + +/* USB Endpoint List Address register ENDPOINTLISTADDR -- Device Mode */ + +#define USBDEV_ENDPOINTLIST_EPBASE_SHIFT (11) /* Bits 11-31: Endpoint list pointer (low) */ +#define USBDEV_ENDPOINTLIST_EPBASE_MASK (0x1fffff << USBDEV_ENDPOINTLIST_EPBASE_SHIFT) + +/* USB burst size register BURSTSIZE -- Device/Host Mode */ + +#define USBDEV_BURSTSIZE_TXPBURST_SHIFT (8) /* Bits 8-15: Programmable TX burst length */ +#define USBDEV_BURSTSIZE_TXPBURST_MASK (0xff << USBDEV_BURSTSIZE_TXPBURST_SHIFT) +#define USBDEV_BURSTSIZE_RXPBURST_SHIFT (0) /* Bits 0-7: RXPBURST Programmable RX burst length */ +#define USBDEV_BURSTSIZE_RXPBURST_MASK (0xff << USBDEV_BURSTSIZE_RXPBURST_SHIFT) + +#define USBHOST_BURSTSIZE_TXPBURST_SHIFT (8) /* Bits 8-15: Programmable TX burst length */ +#define USBHOST_BURSTSIZE_TXPBURST_MASK (0xff << USBHOST_BURSTSIZE_TXPBURST_SHIFT) +#define USBHOST_BURSTSIZE_RXPBURST_SHIFT (0) /* Bits 0-7: RXPBURST Programmable RX burst length */ +#define USBHOST_BURSTSIZE_RXPBURST_MASK (0xff << USBHOST_BURSTSIZE_RXPBURST_SHIFT) + +/* USB Transfer buffer Fill Tuning register TXFIFOFILLTUNING -- Host Mode */ + +#define USBHOST_TXFILLTUNING_FIFOTHRES_SHIFT (16) /* Bits 16-21: Scheduler overhead */ +#define USBHOST_TXFILLTUNING_FIFOTHRES_MASK (0x3f << USBHOST_TXFILLTUNING_FIFOTHRES_SHIFT) +#define USBHOST_TXFILLTUNING_SCHEATLTH_SHIFT (8) /* Bits 8-12: Scheduler health counter */ +#define USBHOST_TXFILLTUNING_SCHEATLTH_MASK (0x1f << USBHOST_TXFILLTUNING_SCHEATLTH_SHIFT) +#define USBHOST_TXFILLTUNING_SCHOH_SHIFT (0) /* Bits 0-7: FIFO burst threshold */ +#define USBHOST_TXFILLTUNING_SCHOH_MASK (0x7f << USBHOST_TXFILLTUNING_SCHOH_SHIFT) + +/* USB endpoint NAK register ENDPTNAK -- Device Mode */ + +#define USBDEV_ENDPTNAK_EPTN_SHIFT (16) /* Bits 16-23: Tx endpoint NAK */ +#define USBDEV_ENDPTNAK_EPTN_MASK (0xff << USBDEV_ENDPTNAK_EPTN_SHIFT) +#define USBDEV_ENDPTNAK_EPRN_SHIFT (0) /* Bits 0-7: Rx endpoint NAK */ +#define USBDEV_ENDPTNAK_EPRN_MASK (0xff << USBDEV_ENDPTNAK_EPRN_SHIFT) + +/* USB Endpoint NAK Enable register ENDPTNAKEN -- Device Mode */ + +#define USBDEV_ENDPTNAK_EPTNE_SHIFT (16) /* Bits 16-23: Tx endpoint NAK enable */ +#define USBDEV_ENDPTNAK_EPTNE_MASK (0xff << USBDEV_ENDPTNAK_EPTNE_SHIFT) +#define USBDEV_ENDPTNAK_EPRNE_SHIFT (0) /* Bits 0-7: Rx endpoint NAK enable */ +#define USBDEV_ENDPTNAK_EPRNE_MASK (0xff << USBDEV_ENDPTNAK_EPRNE_SHIFT) + +/* Configure Flag register CONFIGFLAG -- Not used, returns 1 */ + +#define USBDEV_CONFIGFLAG_CF (1) + +/* Port Status and Control register PRTSC1 -- Device Mode */ + +#define USBDEV_PRTSC1_PSPD_SHIFT (26) /* Bits 26-27: Port speed */ +#define USBDEV_PRTSC1_PSPD_MASK (0x3 << USBDEV_PRTSC1_PSPD_SHIFT) +# define USBDEV_PRTSC1_PSPD_FS (0 << USBDEV_PRTSC1_PSPD_SHIFT) /* Full-speed */ +# define USBDEV_PRTSC1_PSPD_LS (1 << USBDEV_PRTSC1_PSPD_SHIFT) /* Low-speed */ +# define USBDEV_PRTSC1_PSPD_HS (2 << USBDEV_PRTSC1_PSPD_SHIFT) /* High-speed */ + +#define USBDEV_PRTSC1_PFSC (1 << 24) /* Bit 24: Port force full speed connect */ +#define USBDEV_PRTSC1_PHCD (1 << 23) /* Bit 23: PHY low power suspend - clock disable (PLPSCD) */ +#define USBDEV_PRTSC1_PTC_SHIFT (16) /* Bits 16-19: 19: Port test control */ +#define USBDEV_PRTSC1_PTC_MASK (0xf << USBDEV_PRTSC1_PTC_SHIFT) +# define USBDEV_PRTSC1_PTC_DISABLE (0 << USBDEV_PRTSC1_PTC_SHIFT) /* TEST_MODE_DISABLE */ +# define USBDEV_PRTSC1_PTC_JSTATE (1 << USBDEV_PRTSC1_PTC_SHIFT) /* J_STATE */ +# define USBDEV_PRTSC1_PTC_KSTATE (2 << USBDEV_PRTSC1_PTC_SHIFT) /* K_STATE */ +# define USBDEV_PRTSC1_PTC_SE0 (3 << USBDEV_PRTSC1_PTC_SHIFT) /* SE0 (host)/NAK (device) */ +# define USBDEV_PRTSC1_PTC_PACKET (4 << USBDEV_PRTSC1_PTC_SHIFT) /* Packet */ +# define USBDEV_PRTSC1_PTC_HS (5 << USBDEV_PRTSC1_PTC_SHIFT) /* FORCE_ENABLE_HS */ +# define USBDEV_PRTSC1_PTC_FS (6 << USBDEV_PRTSC1_PTC_SHIFT) /* FORCE_ENABLE_FS */ + +#define USBDEV_PRTSC1_PIC_SHIFT (14) /* Bits 14-15: Port indicator control */ +#define USBDEV_PRTSC1_PIC_MASK (0x3 << USBDEV_PRTSC1_PIC_SHIFT) +# define USBDEV_PRTSC1_PIC_OFF (0 << USBDEV_PRTSC1_PIC_SHIFT) /* 00 Port indicators are off */ +# define USBDEV_PRTSC1_PIC_AMBER (1 << USBDEV_PRTSC1_PIC_SHIFT) /* 01 amber */ +# define USBDEV_PRTSC1_PIC_GREEN (2 << USBDEV_PRTSC1_PIC_SHIFT) /* 10 green */ + +#define USBDEV_PRTSC1_HSP (1 << 9) /* Bit 9: High-speed status */ +#define USBDEV_PRTSC1_PR (1 << 8) /* Bit 8: Port reset */ +#define USBDEV_PRTSC1_SUSP (1 << 7) /* Bit 7: Suspend */ +#define USBDEV_PRTSC1_FPR (1 << 6) /* Bit 6: Force port resume */ +#define USBDEV_PRTSC1_PEC (1 << 3) /* Bit 3: Port enable/disable change */ +#define USBDEV_PRTSC1_PE (1 << 2) /* Bit 2: Port enable */ +#define USBDEV_PRTSC1_CCS (1 << 0) /* Bit 0: Current connect status */ + +/* Port Status and Control register PRTSC1 -- Host Mode */ + +#define USBHOST_PRTSC1_PSPD_SHIFT (26) /* Bits 26-27: Port speed */ +#define USBHOST_PRTSC1_PSPD_MASK (0x3 << USBHOST_PRTSC1_PSPD_SHIFT) +# define USBHOST_PRTSC1_PSPD_FS (0 << USBHOST_PRTSC1_PSPD_SHIFT) /* Full-speed */ +# define USBHOST_PRTSC1_PSPD_LS (1 << USBHOST_PRTSC1_PSPD_SHIFT) /* Low-speed */ +# define USBHOST_PRTSC1_PSPD_HS (2 << USBHOST_PRTSC1_PSPD_SHIFT) /* High-speed */ + +#define USBHOST_PRTSC1_PFSC (1 << 24) /* Bit 24: Port force full speed connect */ +#define USBHOST_PRTSC1_PHCD (1 << 23) /* Bit 23: PHY low power suspend - clock disable (PLPSCD) */ +#define USBHOST_PRTSC1_WKOC (1 << 22) /* Bit 22: Wake on over-current enable (WKOC_E) */ +#define USBHOST_PRTSC1_WKDC (1 << 21) /* Bit 21: Wake on disconnect enable (WKDSCNNT_E) */ +#define USBHOST_PRTSC1_WKCN (1 << 20) /* Bit 20: Wake on connect enable (WKCNNT_E) */ +#define USBHOST_PRTSC1_PTC_SHIFT (16) /* Bits 16-19: Port test control */ +#define USBHOST_PRTSC1_PTC_MASK (0xf << USBHOST_PRTSC1_PTC_SHIFT) +# define USBHOST_PRTSC1_PTC_DISABLE (0 << USBHOST_PRTSC1_PTC_SHIFT) /* 0000 TEST_MODE_DISABLE */ +# define USBHOST_PRTSC1_PTC_JSTATE (1 << USBHOST_PRTSC1_PTC_SHIFT) /* 0001 J_STATE */ +# define USBHOST_PRTSC1_PTC_KSTATE (2 << USBHOST_PRTSC1_PTC_SHIFT) /* 0010 K_STATE */ +# define USBHOST_PRTSC1_PTC_SE0 (3 << USBHOST_PRTSC1_PTC_SHIFT) /* 0011 SE0 (host)/NAK (device) */ +# define USBHOST_PRTSC1_PTC_PACKET (4 << USBHOST_PRTSC1_PTC_SHIFT) /* 0100 Packet */ +# define USBHOST_PRTSC1_PTC_HS (5 << USBHOST_PRTSC1_PTC_SHIFT) /* 0101 FORCE_ENABLE_HS */ +# define USBHOST_PRTSC1_PTC_FS (6 << USBHOST_PRTSC1_PTC_SHIFT) /* 0110 FORCE_ENABLE_FS */ +# define USBHOST_PRTSC1_PTC_LS (7 << USBHOST_PRTSC1_PTC_SHIFT) /* 0111 FORCE_ENABLE_LS */ + +#define USBHOST_PRTSC1_PIC_SHIFT (14) /* Bits 14-15: Port indicator control */ +#define USBHOST_PRTSC1_PIC_MASK (0x3 << USBHOST_PRTSC1_PIC_SHIFT) +# define USBHOST_PRTSC1_PIC_OFF (0 << USBHOST_PRTSC1_PIC_SHIFT) /* 00 Port indicators are off */ +# define USBHOST_PRTSC1_PIC_AMBER (1 << USBHOST_PRTSC1_PIC_SHIFT) /* 01 Amber */ +# define USBHOST_PRTSC1_PIC_GREEN (2 << USBHOST_PRTSC1_PIC_SHIFT) /* 10 Green */ + +#define USBHOST_PRTSC1_PP (1 << 12) /* Bit 12: Port power control */ +#define USBHOST_PRTSC1_LS_SHIFT (10) /* Bits 10-11: Line status */ +#define USBHOST_PRTSC1_LS_MASK (0x3 << USBHOST_PRTSC1_LS_SHIFT) +# define USBHOST_PRTSC1_LS_SE0 (0 << USBHOST_PRTSC1_LS_SHIFT) /* SE0 (USB_DP and USB_DM LOW) */ +# define USBHOST_PRTSC1_LS_JSTATE (2 << USBHOST_PRTSC1_LS_SHIFT) /* J-state (USB_DP HIGH and USB_DM LOW) */ +# define USBHOST_PRTSC1_LS_KSTATE (1 << USBHOST_PRTSC1_LS_SHIFT) /* K-state (USB_DP LOW and USB_DM HIGH) */ + +#define USBHOST_PRTSC1_HSP (1 << 9) /* Bit 9: High-speed status */ +#define USBHOST_PRTSC1_PR (1 << 8) /* Bit 8: Port reset */ +#define USBHOST_PRTSC1_SUSP (1 << 7) /* Bit 7: Suspend */ +#define USBHOST_PRTSC1_FPR (1 << 6) /* Bit 6: Force port resume */ +#define USBHOST_PRTSC1_OCC (1 << 5) /* Bit 5: Over-current change */ +#define USBHOST_PRTSC1_OCA (1 << 4) /* Bit 4: Over-current active */ +#define USBHOST_PRTSC1_PEC (1 << 3) /* Bit 3: Port disable/enable change */ +#define USBHOST_PRTSC1_PE (1 << 2) /* Bit 2: Port enable */ +#define USBHOST_PRTSC1_CSC (1 << 1) /* Bit 1: Connect status change */ +#define USBHOST_PRTSC1_CCS (1 << 0) /* Bit 0: Current connect status */ + +/* OTG Status and Control register (OTGSC) */ + +/* OTG interrupt enable */ + +#define USBOTG_OTGSC_DPIE (1 << 30) /* Bit 30: Data pulse interrupt enable */ +#define USBOTG_OTGSC_1MSE (1 << 29) /* Bit 29: 1 millisecond timer interrupt enable */ +#define USBOTG_OTGSC_BSEIE (1 << 28) /* Bit 28: B-session end interrupt enable */ +#define USBOTG_OTGSC_BSVIE (1 << 27) /* Bit 27: B-session valid interrupt enable */ +#define USBOTG_OTGSC_ASVIE (1 << 26) /* Bit 26: A-session valid interrupt enable */ +#define USBOTG_OTGSC_AVVIE (1 << 25) /* Bit 25: A-VBUS valid interrupt enable */ +#define USBOTG_OTGSC_IDIE (1 << 24) /* Bit 24: USB ID interrupt enable */ + +/* OTG interrupt status */ + +#define USBOTG_OTGSC_DPIS (1 << 22) /* Bit 22: Data pulse interrupt status */ +#define USBOTG_OTGSC_1MSS (1 << 21) /* Bit 21: 1 millisecond timer interrupt status */ +#define USBOTG_OTGSC_BSEIS (1 << 20) /* Bit 20: B-Session end interrupt status */ +#define USBOTG_OTGSC_BSVIS (1 << 19) /* Bit 19: B-Session valid interrupt status */ +#define USBOTG_OTGSC_ASVIS (1 << 18) /* Bit 18: A-Session valid interrupt status */ +#define USBOTG_OTGSC_AVVIS (1 << 17) /* Bit 17: A-VBUS valid interrupt status */ +#define USBOTG_OTGSC_IDIS (1 << 16) /* Bit 16: USB ID interrupt status */ + +/* OTG status inputs */ + +#define USBOTG_OTGSC_DPS (1 << 14) /* Bit 14: Data bus pulsing status */ +#define USBOTG_OTGSC_1MST (1 << 13) /* Bit 13: 1 millisecond timer toggle */ +#define USBOTG_OTGSC_BSE (1 << 12) /* Bit 12: B-session end */ +#define USBOTG_OTGSC_BSV (1 << 11) /* Bit 11: B-session valid */ +#define USBOTG_OTGSC_ASV (1 << 10) /* Bit 10: A-session valid */ +#define USBOTG_OTGSC_AVV (1 << 9) /* Bit 9: A-VBUS valid */ +#define USBOTG_OTGSC_ID (1 << 8) /* Bit 8: USB ID */ + +/* OTG controls */ + +#define USBOTG_OTGSC_IDPU (1 << 5) /* Bit 5: ID pull-up */ +#define USBOTG_OTGSC_DP (1 << 4) /* Bit 4: Data pulsing */ +#define USBOTG_OTGSC_OT (1 << 3) /* Bit 3: OTG termination */ +#define USBOTG_OTGSC_VC (1 << 1) /* Bit 1: VBUS_Charge */ +#define USBOTG_OTGSC_VD (1 << 0) /* Bit 0: VBUS_Discharge */ + +/* USB Mode register USBMODE -- Device Mode */ + +#define USBDEV_USBMODE_SDIS (1 << 4) /* Bit 4: Stream disable mode */ +#define USBDEV_USBMODE_SLOM (1 << 3) /* Bit 3: Setup Lockout mode */ +#define USBDEV_USBMODE_ES (1 << 2) /* Bit 2: Endian select */ +#define USBDEV_USBMODE_CM_SHIFT (0) /* Bits 0-1: Controller mode */ +#define USBDEV_USBMODE_CM_MASK (0x3 << USBDEV_USBMODE_CM_SHIFT) +# define USBDEV_USBMODE_CM_IDLE (0 << USBDEV_USBMODE_CM_SHIFT) /* Idle */ +# define USBDEV_USBMODE_CM_DEVICE (2 << USBDEV_USBMODE_CM_SHIFT) /* Device controller */ +# define USBDEV_USBMODE_CM_HOST (3 << USBDEV_USBMODE_CM_SHIFT) /* Host controller */ + +/* USB Mode register USBMODE -- Host Mode */ + +#define USBHOST_USBMODE_SDIS (1 << 4) /* Bit 4: Stream disable mode */ +#define USBHOST_USBMODE_ES (1 << 2) /* Bit 2: Endian select */ +#define USBHOST_USBMODE_CM_SHIFT (0) /* Bits 0-1: Controller mode */ +#define USBHOST_USBMODE_CM_MASK (0x3 << USBHOST_USBMODE_CM_SHIFT) +# define USBHOST_USBMODE_CM_IDLE (0 << USBHOST_USBMODE_CM_SHIFT) /* Idle */ +# define USBHOST_USBMODE_CM_DEVICE (2 << USBHOST_USBMODE_CM_SHIFT) /* Device controller */ +# define USBHOST_USBMODE_CM_HOST (3 << USBHOST_USBMODE_CM_SHIFT) /* Host controller */ + +/* Device endpoint registers */ + +/* USB Endpoint Setup Status register ENDPTSETUPSTAT */ + +#define USBDEV_ENDPTSETSTAT_STAT15 (1 << 15) /* Bit 15: Setup EP status for logical EP 15 */ +#define USBDEV_ENDPTSETSTAT_STAT14 (1 << 14) /* Bit 14: Setup EP status for logical EP 14 */ +#define USBDEV_ENDPTSETSTAT_STAT13 (1 << 13) /* Bit 13: Setup EP status for logical EP 13 */ +#define USBDEV_ENDPTSETSTAT_STAT12 (1 << 12) /* Bit 12: Setup EP status for logical EP 12 */ +#define USBDEV_ENDPTSETSTAT_STAT11 (1 << 11) /* Bit 11: Setup EP status for logical EP 11 */ +#define USBDEV_ENDPTSETSTAT_STAT10 (1 << 10) /* Bit 10: Setup EP status for logical EP 10 */ +#define USBDEV_ENDPTSETSTAT_STAT9 (1 << 9) /* Bit 9: Setup EP status for logical EP 9 */ +#define USBDEV_ENDPTSETSTAT_STAT8 (1 << 8) /* Bit 8: Setup EP status for logical EP 8 */ +#define USBDEV_ENDPTSETSTAT_STAT7 (1 << 7) /* Bit 7: Setup EP status for logical EP 7 */ +#define USBDEV_ENDPTSETSTAT_STAT6 (1 << 6) /* Bit 6: Setup EP status for logical EP 6 */ +#define USBDEV_ENDPTSETSTAT_STAT5 (1 << 5) /* Bit 5: Setup EP status for logical EP 5 */ +#define USBDEV_ENDPTSETSTAT_STAT4 (1 << 4) /* Bit 4: Setup EP status for logical EP 4 */ +#define USBDEV_ENDPTSETSTAT_STAT3 (1 << 3) /* Bit 3: Setup EP status for logical EP 3 */ +#define USBDEV_ENDPTSETSTAT_STAT2 (1 << 2) /* Bit 2: Setup EP status for logical EP 2 */ +#define USBDEV_ENDPTSETSTAT_STAT1 (1 << 1) /* Bit 1: Setup EP status for logical EP 1 */ +#define USBDEV_ENDPTSETSTAT_STAT0 (1 << 0) /* Bit 0: Setup EP status for logical EP 0 */ + +/* USB Endpoint Prime register ENDPTPRIME */ + +#define USBDEV_ENDPTPRIM_PETB7 (1 << 23) /* Bit 23: Prime EP xmt buffer for physical IN EP 7 */ +#define USBDEV_ENDPTPRIM_PETB6 (1 << 22) /* Bit 22: Prime EP xmt buffer for physical IN EP 6 */ +#define USBDEV_ENDPTPRIM_PETB5 (1 << 21) /* Bit 21: Prime EP xmt buffer for physical IN EP 5 */ +#define USBDEV_ENDPTPRIM_PETB4 (1 << 20) /* Bit 20: Prime EP xmt buffer for physical IN EP 4 */ +#define USBDEV_ENDPTPRIM_PETB3 (1 << 19) /* Bit 19: Prime EP xmt buffer for physical IN EP 3 */ +#define USBDEV_ENDPTPRIM_PETB2 (1 << 18) /* Bit 18: Prime EP xmt buffer for physical IN EP 2 */ +#define USBDEV_ENDPTPRIM_PETB1 (1 << 17) /* Bit 17: Prime EP xmt buffer for physical IN EP 1 */ +#define USBDEV_ENDPTPRIM_PETB0 (1 << 16) /* Bit 16: Prime EP xmt buffer for physical IN EP 0 */ +#define USBDEV_ENDPTPRIM_PERB7 (1 << 7) /* Bit 7: Prime EP recv buffer for physical OUT EP 7 */ +#define USBDEV_ENDPTPRIM_PERB6 (1 << 6) /* Bit 6: Prime EP recv buffer for physical OUT EP 6 */ +#define USBDEV_ENDPTPRIM_PERB5 (1 << 5) /* Bit 5: Prime EP recv buffer for physical OUT EP 5 */ +#define USBDEV_ENDPTPRIM_PERB4 (1 << 4) /* Bit 4: Prime EP recv buffer for physical OUT EP 4 */ +#define USBDEV_ENDPTPRIM_PERB3 (1 << 3) /* Bit 3: Prime EP recv buffer for physical OUT EP 3 */ +#define USBDEV_ENDPTPRIM_PERB2 (1 << 2) /* Bit 2: Prime EP recv buffer for physical OUT EP 2 */ +#define USBDEV_ENDPTPRIM_PERB1 (1 << 1) /* Bit 1: Prime EP recv buffer for physical OUT EP 1 */ +#define USBDEV_ENDPTPRIM_PERB0 (1 << 0) /* Bit 0: Prime EP recv buffer for physical OUT EP 0 */ + +/* USB Endpoint Flush register ENDPTFLUSH */ + +#define USBDEV_ENDPTFLUSH_FETB7 (1 << 23) /* Bit 23: Flush EP xmt buffer for physical IN EP 7 */ +#define USBDEV_ENDPTFLUSH_FETB6 (1 << 22) /* Bit 22: Flush EP xmt buffer for physical IN EP 6 */ +#define USBDEV_ENDPTFLUSH_FETB5 (1 << 21) /* Bit 21: Flush EP xmt buffer for physical IN EP 5 */ +#define USBDEV_ENDPTFLUSH_FETB4 (1 << 20) /* Bit 20: Flush EP xmt buffer for physical IN EP 4 */ +#define USBDEV_ENDPTFLUSH_FETB3 (1 << 19) /* Bit 19: Flush EP xmt buffer for physical IN EP 3 */ +#define USBDEV_ENDPTFLUSH_FETB2 (1 << 18) /* Bit 18: Flush EP xmt buffer for physical IN EP 2 */ +#define USBDEV_ENDPTFLUSH_FETB1 (1 << 17) /* Bit 17: Flush EP xmt buffer for physical IN EP 1 */ +#define USBDEV_ENDPTFLUSH_FETB0 (1 << 16) /* Bit 16: Flush EP xmt buffer for physical IN EP 0 */ +#define USBDEV_ENDPTFLUSH_FERB7 (1 << 7) /* Bit 7: Flush EP recv buffer for physical OUT EP 7 */ +#define USBDEV_ENDPTFLUSH_FERB6 (1 << 6) /* Bit 6: Flush EP recv buffer for physical OUT EP 6 */ +#define USBDEV_ENDPTFLUSH_FERB5 (1 << 5) /* Bit 5: Flush EP recv buffer for physical OUT EP 5 */ +#define USBDEV_ENDPTFLUSH_FERB4 (1 << 4) /* Bit 4: Flush EP recv buffer for physical OUT EP 4 */ +#define USBDEV_ENDPTFLUSH_FERB3 (1 << 3) /* Bit 3: Flush EP recv buffer for physical OUT EP 3 */ +#define USBDEV_ENDPTFLUSH_FERB2 (1 << 2) /* Bit 2: Flush EP recv buffer for physical OUT EP 2 */ +#define USBDEV_ENDPTFLUSH_FERB1 (1 << 1) /* Bit 1: Flush EP recv buffer for physical OUT EP 1 */ +#define USBDEV_ENDPTFLUSH_FERB0 (1 << 0) /* Bit 0: Flush EP recv buffer for physical OUT EP 0 */ + +/* USB Endpoint Status register ENDPTSTATUS */ + +#define USBDEV_ENDPTSTATUS_ETBR7 (1 << 23) /* Bit 23: EP xmt buffer ready for physical IN EP 7 */ +#define USBDEV_ENDPTSTATUS_ETBR6 (1 << 22) /* Bit 22: EP xmt buffer ready for physical IN EP 6 */ +#define USBDEV_ENDPTSTATUS_ETBR5 (1 << 21) /* Bit 21: EP xmt buffer ready for physical IN EP 5 */ +#define USBDEV_ENDPTSTATUS_ETBR4 (1 << 20) /* Bit 20: EP xmt buffer ready for physical IN EP 4 */ +#define USBDEV_ENDPTSTATUS_ETBR3 (1 << 19) /* Bit 19: EP xmt buffer ready for physical IN EP 3 */ +#define USBDEV_ENDPTSTATUS_ETBR2 (1 << 18) /* Bit 18: EP xmt buffer ready for physical IN EP 2 */ +#define USBDEV_ENDPTSTATUS_ETBR1 (1 << 17) /* Bit 17: EP xmt buffer ready for physical IN EP 1 */ +#define USBDEV_ENDPTSTATUS_ETBR0 (1 << 16) /* Bit 16: EP xmt buffer ready for physical IN EP 0 */ +#define USBDEV_ENDPTSTATUS_ERBR7 (1 << 7) /* Bit 7: EP recv buffer ready for physical OUT EP 7 */ +#define USBDEV_ENDPTSTATUS_ERBR6 (1 << 6) /* Bit 6: EP recv buffer ready for physical OUT EP 6 */ +#define USBDEV_ENDPTSTATUS_ERBR5 (1 << 5) /* Bit 5: EP recv buffer ready for physical OUT EP 5 */ +#define USBDEV_ENDPTSTATUS_ERBR4 (1 << 4) /* Bit 4: EP recv buffer ready for physical OUT EP 4 */ +#define USBDEV_ENDPTSTATUS_ERBR3 (1 << 3) /* Bit 3: EP recv buffer ready for physical OUT EP 3 */ +#define USBDEV_ENDPTSTATUS_ERBR2 (1 << 2) /* Bit 2: EP recv buffer ready for physical OUT EP 2 */ +#define USBDEV_ENDPTSTATUS_ERBR1 (1 << 1) /* Bit 1: EP recv buffer ready for physical OUT EP 1 */ +#define USBDEV_ENDPTSTATUS_ERBR0 (1 << 0) /* Bit 0: EP recv buffer ready for physical OUT EP 0 */ + +/* USB Endpoint Complete register ENDPTCOMPLETE */ + +#define USBDEV_ENDPTCOMPLETE_ETCE7 (1 << 23) /* Bit 23: EP xmt complete event for physical IN EP 7 */ +#define USBDEV_ENDPTCOMPLETE_ETCE6 (1 << 22) /* Bit 22: EP xmt complete event for physical IN EP 6 */ +#define USBDEV_ENDPTCOMPLETE_ETCE5 (1 << 21) /* Bit 21: EP xmt complete event for physical IN EP 5 */ +#define USBDEV_ENDPTCOMPLETE_ETCE4 (1 << 20) /* Bit 20: EP xmt complete event for physical IN EP 4 */ +#define USBDEV_ENDPTCOMPLETE_ETCE3 (1 << 19) /* Bit 19: EP xmt complete event for physical IN EP 3 */ +#define USBDEV_ENDPTCOMPLETE_ETCE2 (1 << 18) /* Bit 18: EP xmt complete event for physical IN EP 2 */ +#define USBDEV_ENDPTCOMPLETE_ETCE1 (1 << 17) /* Bit 17: EP xmt complete event for physical IN EP 1 */ +#define USBDEV_ENDPTCOMPLETE_ETCE0 (1 << 16) /* Bit 16: EP xmt complete event for physical IN EP 0 */ +#define USBDEV_ENDPTCOMPLETE_ERCE7 (1 << 7) /* Bit 7: EP recv complete event for physical OUT EP 7 */ +#define USBDEV_ENDPTCOMPLETE_ERCE6 (1 << 6) /* Bit 6: EP recv complete event for physical OUT EP 6 */ +#define USBDEV_ENDPTCOMPLETE_ERCE5 (1 << 5) /* Bit 5: EP recv complete event for physical OUT EP 5 */ +#define USBDEV_ENDPTCOMPLETE_ERCE4 (1 << 4) /* Bit 4: EP recv complete event for physical OUT EP 4 */ +#define USBDEV_ENDPTCOMPLETE_ERCE3 (1 << 3) /* Bit 3: EP recv complete event for physical OUT EP 3 */ +#define USBDEV_ENDPTCOMPLETE_ERCE2 (1 << 2) /* Bit 2: EP recv complete event for physical OUT EP 2 */ +#define USBDEV_ENDPTCOMPLETE_ERCE1 (1 << 1) /* Bit 1: EP recv complete event for physical OUT EP 1 */ +#define USBDEV_ENDPTCOMPLETE_ERCE0 (1 << 0) /* Bit 0: EP recv complete event for physical OUT EP 0 */ + +/* USB Endpoint 0 Control register ENDPTCTRL0 */ + +#define USBDEV_ENDPTCTRL0_TXE (1 << 23) /* Bit 23: Tx endpoint enable */ +#define USBDEV_ENDPTCTRL0_TXT_SHIFT (18) /* Bits 18-19: Tx endpoint type */ +#define USBDEV_ENDPTCTRL0_TXT_MASK (0x3 << USBDEV_ENDPTCTRL0_TXT_SHIFT) +# define USBDEV_ENDPTCTRL0_TXT_CTRL (0 << USBDEV_ENDPTCTRL0_TXT_SHIFT) /* Control */ + +#define USBDEV_ENDPTCTRL0_TXS (1 << 16) /* Bit 16: Tx endpoint stall */ +#define USBDEV_ENDPTCTRL0_RXE (1 << 7) /* Bit 7: Rx endpoint enable */ +#define USBDEV_ENDPTCTRL0_RXT_SHIFT (2) /* Bits 2-3: Endpoint type */ +#define USBDEV_ENDPTCTR0L_RXT_MASK (0x3 << USBDEV_ENDPTCTRL0_RXT_SHIFT) +# define USBDEV_ENDPTCTRL0_RXT_CTRL (0 << USBDEV_ENDPTCTRL0_RXT_SHIFT) /* Control */ + +#define USBDEV_ENDPTCTRL0_RXS (1 << 0) /* Bit 0: Rx endpoint stall */ + +/* USB Endpoint 1-7 control registers ENDPTCTRL1-ENDPPTCTRL7 */ + +#define USBDEV_ENDPTCTRL_TXE (1 << 23) /* Bit 23: Tx endpoint enable */ +#define USBDEV_ENDPTCTRL_TXR (1 << 22) /* Bit 22: Tx data toggle reset */ +#define USBDEV_ENDPTCTRL_TXI (1 << 21) /* Bit 21: Tx data toggle inhibit */ +#define USBDEV_ENDPTCTRL_TXT_SHIFT (18) /* Bits 18-19: Tx endpoint type */ +#define USBDEV_ENDPTCTRL_TXT_MASK (0x3 << USBDEV_ENDPTCTRL_TXT_SHIFT) +# define USBDEV_ENDPTCTRL_TXT_CTRL (0 << USBDEV_ENDPTCTRL_TXT_SHIFT) /* Control */ +# define USBDEV_ENDPTCTRL_TXT_ISOC (1 << USBDEV_ENDPTCTRL_TXT_SHIFT) /* Isochronous */ +# define USBDEV_ENDPTCTRL_TXT_BULK (2 << USBDEV_ENDPTCTRL_TXT_SHIFT) /* Bulk */ +# define USBDEV_ENDPTCTRL_TXT_INTR (3 << USBDEV_ENDPTCTRL_TXT_SHIFT) /* Interrupt */ + +#define USBDEV_ENDPTCTRL_TXS (1 << 16) /* Bit 16: Tx endpoint stall */ +#define USBDEV_ENDPTCTRL_RXE (1 << 7) /* Bit 7: Rx endpoint enable */ +#define USBDEV_ENDPTCTRL_RXR (1 << 6) /* Bit 6: Rx data toggle reset */ +#define USBDEV_ENDPTCTRL_RXI (1 << 5) /* Bit 5: Rx data toggle inhibit */ +#define USBDEV_ENDPTCTRL_RXT_SHIFT (2) /* Bits 2-3: Endpoint type */ +#define USBDEV_ENDPTCTRL_RXT_MASK (0x3 << USBDEV_ENDPTCTRL_RXT_SHIFT) +# define USBDEV_ENDPTCTRL_RXT_CTRL (0 << USBDEV_ENDPTCTRL_RXT_SHIFT) /* Control */ +# define USBDEV_ENDPTCTRL_RXT_ISOC (1 << USBDEV_ENDPTCTRL_RXT_SHIFT) /* Isochronous */ +# define USBDEV_ENDPTCTRL_RXT_BULK (2 << USBDEV_ENDPTCTRL_RXT_SHIFT) /* Bulk */ +# define USBDEV_ENDPTCTRL_RXT_INTR (3 << USBDEV_ENDPTCTRL_RXT_SHIFT) /* Interrupt */ + +#define USBDEV_ENDPTCTRL_RXS (1 << 0) /* Bit 0: Rx endpoint stall */ + +/* Device non-core registers */ + +/* USB OTG Control register 1 */ + +#define USBNC_CTRL1_WIR (1 << 31) /* Bit 31: Wake-up Interrupt Request */ +#define USBNC_CTRL1_WKUP_DPDM_EN (1 << 29) /* Bit 29: Wake-up on DP/DM change enable */ +#define USBNC_CTRL1_WKUP_VBUS_EN (1 << 17) /* Bit 17: Wake-up on VBUS change enable */ +#define USBNC_CTRL1_WKUP_ID_EN (1 << 16) /* Bit 16: Wake-up on ID change enable */ +#define USBNC_CTRL1_WKUP_SW (1 << 15) /* Bit 15: Software Wake-up */ +#define USBNC_CTRL1_WKUP_SW_EN (1 << 14) /* Bit 14: Software Wake-up Enable */ +#define USBNC_CTRL1_WIE (1 << 10) /* Bit 10: Wake-up Interrupt Enable */ +#define USBNC_CTRL1_PWR_POL (1 << 9) /* Bit 9: Power Polarity */ +#define USBNC_CTRL1_OVER_CUR_POL (1 << 8) /* Bit 8: Polarity of Overcurrent */ +#define USBNC_CTRL1_OVER_CUR_DIS (1 << 7) /* Bit 7: Disable Overcurrent Detection */ + +/* USB OTG Control register 2 */ + +#define USBNC_CTRL2_UTMI_CLK_VLD (1 << 31) /* Bit 31: UTMI clock to the USB PHY is valid */ +#define USBNC_CTRL2_SHORT_PKT_EN (1 << 23) /* Bit 23: Short Packet Interrupt enable */ +#define USBNC_CTRL2_LOWSPEED_EN (1 << 3) /* Bit 3: Low speed enable */ +#define USBNC_CTRL2_AUTURESUME_EN (1 << 2) /* Bit 2: Auto Resume Enable */ +#define USBNC_CTRL2_VBUS_SOURCE_SEL_MASK (0x3) /* Bits 0-1: VBUS source select at VBUS wakeup event */ + +/* PHY Configure 1 -- internal control register bits of the PHY clock */ + +#define USBNC_UTMIPHY_CFG1_TXPREEMPPULSETUNE0 (1 << 30) /* Bit 30: HS Transmitter Pre-Emphasis Duration Control */ +#define USBNC_UTMIPHY_CFG1_TXPREEMPAMPTUNE0_SHIFT (28) /* Bits 28-29: HS Transmitter Pre-Emphasis Current Control */ +#define USBNC_UTMIPHY_CFG1_TXPREEMPAMPTUNE0_MASK (0x3 << 28) +#define USBNC_UTMIPHY_CFG1_TXRESTUNE0_SHIFT (26) /* Bits 26-27: USB Source Impedance Adjustment */ +#define USBNC_UTMIPHY_CFG1_TXRESTUNE0_MASK (0x3 << 26) +#define USBNC_UTMIPHY_CFG1_TXRISETUNE0_SHIFT (24) /* Bits 24-25: HS Transmitter Rise/Fall Time Adjustment */ +#define USBNC_UTMIPHY_CFG1_TXRISETUNE0_MASK (0x3 << 24) +#define USBNC_UTMIPHY_CFG1_TXVREFTUNE0_SHIFT (20) /* Bits 20-23: HS DC Voltage Level Adjustment */ +#define USBNC_UTMIPHY_CFG1_TXVREFTUNE0_MASK (0xf << 20) +#define USBNC_UTMIPHY_CFG1_TXFSLSTUNE0_SHIFT (16) /* Bits 16-19: FS/LS Source Impedance Adjustment */ +#define USBNC_UTMIPHY_CFG1_TXFSLSTUNE0_MASK (0xf << 16) +#define USBNC_UTMIPHY_CFG1_PHY_POR_SW (1 << 15) /* Bit 15 : PHY software POR */ +#define USBNC_UTMIPHY_CFG1_TXHSXVTUNE_SHIFT (13) /* Bits 13-14: Transmitter High-Speed Crossover Adjustment */ +#define USBNC_UTMIPHY_CFG1_TXHSXVTUNE_MASK (0x3 << 13) +#define USBNC_UTMIPHY_CFG1_OTGTUNE0_SHIFT (10) /* Bits 10-12: VBUS Valid Threshold Adjustment */ +#define USBNC_UTMIPHY_CFG1_OTGTUNE0_MASK (0x7 << 10) +#define USBNC_UTMIPHY_CFG1_SQRXTUNE0_SHIFT (7) /* Bits 7-9: Squelch Threshold Adjustment */ +#define USBNC_UTMIPHY_CFG1_SQRXTUNE0_MASK (0x7 << 7) +#define USBNC_UTMIPHY_CFG1_COMPDISTUNE0_SHIFT (4) /* Bits 4-6: Disconnect Threshold Adjustment */ +#define USBNC_UTMIPHY_CFG1_COMPDISTUNE0_MASK (0x7 << 4) + +#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_USBOTG_H */ diff --git a/arch/arm64/src/imx9/imx93_lowputc.S b/arch/arm64/src/imx9/imx93_lowputc.S new file mode 100644 index 0000000000000..f3311810e05dd --- /dev/null +++ b/arch/arm64/src/imx9/imx93_lowputc.S @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx93_lowputs.S + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + **************************************************************************** + * + * DESCRIPTION + * Wrapper for early printk + * + ***************************************************************************/ + +#include + +#include "arm64_macro.inc" + +#include "hardware/imx9_lpuart.h" +#include "hardware/imx93/imx93_memorymap.h" + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .file "imx93_lowputc.S" + +/**************************************************************************** + * Assembly Macros + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* PL011 UART initialization */ + +GTEXT(arm64_earlyprintinit) +SECTION_FUNC(text, arm64_earlyprintinit) + /* TODO: Assumes u-boot has set us up, assumption is fine for now */ + ret + +/* i.MX93 wait LPUART to be ready to transmit + * rb: register which contains the UART base address + * rc: scratch register + */ +.macro early_uart_ready rb, rc +1: + ldr \rc, [\rb, #UARTSTAT] /* <- Flag register */ + tst \rc, #UARTSTAT_TDRE /* Check FIFO EMPTY bit */ + beq 1b /* Wait for the UART to be ready */ +.endm + +/* i.MX93 LPUART transmit character + * rb: register which contains the UART base address + * rt: register which contains the character to transmit */ +.macro early_uart_transmit rb, rt + str \rt, [\rb, #UARTDATA] /* -> Data Register */ +.endm + +/* + * Print a character on the UART - this function is called by C + * w0: character to print + */ +GTEXT(arm64_lowputc) +SECTION_FUNC(text, arm64_lowputc) + ldr x15, =IMX9_LPUART1_BASE + early_uart_ready x15, w2 + early_uart_transmit x15, w0 + ret diff --git a/arch/arm64/src/imx9/imx9_boot.c b/arch/arm64/src/imx9/imx9_boot.c new file mode 100644 index 0000000000000..16f19de2c6b54 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_boot.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_boot.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#ifdef CONFIG_PAGING +# include +#endif + +#include +#include "arm64_arch.h" +#include "arm64_internal.h" +#include "arm64_mmu.h" +#include "imx9_boot.h" +#include "imx9_serial.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct arm_mmu_region g_mmu_regions[] = +{ + MMU_REGION_FLAT_ENTRY("DEVICE_REGION", + CONFIG_DEVICEIO_BASEADDR, CONFIG_DEVICEIO_SIZE, + MT_DEVICE_NGNRNE | MT_RW | MT_SECURE), + + MMU_REGION_FLAT_ENTRY("DRAM0_S0", + CONFIG_RAMBANK1_ADDR, CONFIG_RAMBANK1_SIZE, + MT_NORMAL | MT_RW | MT_SECURE), +}; + +const struct arm_mmu_config g_mmu_config = +{ + .num_regions = nitems(g_mmu_regions), + .mmu_regions = g_mmu_regions, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm64_el_init + * + * Description: + * The function called from arm64_head.S at very early stage for these + * platform, it's use to: + * - Handling special hardware initialize routine which is need to + * run at high ELs + * - Initialize system software such as hypervisor or security firmware + * which is need to run at high ELs + * + ****************************************************************************/ + +void arm64_el_init(void) +{ +} + +/**************************************************************************** + * Name: arm64_chip_boot + * + * Description: + * Complete boot operations started in arm64_head.S + * + ****************************************************************************/ + +void arm64_chip_boot(void) +{ + /* MAP IO and DRAM, enable MMU. */ + + arm64_mmu_init(true); + + /* Perform board-specific device initialization. This would include + * configuration of board specific resources such as GPIOs, LEDs, etc. + */ + + imx9_board_initialize(); + +#ifdef USE_EARLYSERIALINIT + /* Perform early serial initialization if we are going to use the serial + * driver. + */ + + arm64_earlyserialinit(); +#endif +} diff --git a/arch/arm64/src/imx9/imx9_boot.h b/arch/arm64/src/imx9/imx9_boot.h new file mode 100644 index 0000000000000..cfd10b7e1b2b1 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_boot.h @@ -0,0 +1,79 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_boot.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_BOOT_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_BOOT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: imx9_board_initialize + * + * Description: + * All i.MX9 architectures must provide the following entry point. This + * entry point is called in the initialization phase -- after + * imx_memory_initialize and after all memory has been configured and + * mapped but before any devices have been initialized. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void imx9_board_initialize(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM64_SRC_IMX9_IMX9_BOOT_H */ diff --git a/arch/arm64/src/imx9/imx9_ccm.c b/arch/arm64/src/imx9/imx9_ccm.c new file mode 100644 index 0000000000000..1d8cef9562462 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_ccm.c @@ -0,0 +1,197 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_ccm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "barriers.h" + +#include "arm64_internal.h" +#include "imx9_ccm.h" + +#include "hardware/imx9_ccm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define mb() \ + do \ + { \ + ARM64_DSB(); \ + ARM64_ISB(); \ + } \ + while (0) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_ccm_configure_root_clock + * + * Description: + * Change root clock source and divider. Leaves the clock running state + * unaltered. + * + * Input Parameters: + * root - The root clock index. + * src - The root clock MUX source. + * div - The root clock divider. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int imx9_ccm_configure_root_clock(int root, int src, uint32_t div) +{ + uint32_t value; + int i; + + if (root >= CCM_CR_COUNT || div == 0 || div > 255) + { + return -EINVAL; + } + + /* Find the corresponding MUX register value for root and source */ + + for (i = 0; i < ROOT_MUX_MAX; i++) + { + if (g_ccm_root_mux[root][i] == src) + { + break; + } + } + + if (i == ROOT_MUX_MAX) + { + return -EINVAL; + } + + /* Set the new value */ + + value = CCM_CR_CTRL_MUX_SRCSEL(i) | CCM_CR_CTRL_DIV(div); + putreg32(value, IMX9_CCM_CR_CTRL(root)); + mb(); + + /* Wait for the clock state change */ + + while (getreg32(IMX9_CCM_CR_STAT0(root)) & CCM_CR_STAT0_CHANGING); + + return OK; +} + +/**************************************************************************** + * Name: imx9_ccm_root_clock_on + * + * Description: + * Enable / disable root clock. + * + * Input Parameters: + * root - The root clock index. + * enabled - True enables the clock; false disables it. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int imx9_ccm_root_clock_on(int root, bool enabled) +{ + if (root >= CCM_CR_COUNT) + { + return -EINVAL; + } + + if (enabled) + { + putreg32(CCM_CR_CTRL_OFF, IMX9_CCM_CR_CTRL_CLR(root)); + } + else + { + putreg32(CCM_CR_CTRL_OFF, IMX9_CCM_CR_CTRL_SET(root)); + } + + mb(); + + /* Wait for the clock state change */ + + while (getreg32(IMX9_CCM_CR_STAT0(root)) & CCM_CR_STAT0_CHANGING); + + return OK; +} + +/**************************************************************************** + * Name: imx9_ccm_gate_on + * + * Description: + * Enable / disable clock. + * + * Input Parameters: + * gate - The clock gate index. + * enabled - True enables the clock; false disables it. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int imx9_ccm_gate_on(int gate, bool enabled) +{ + uint32_t value; + + if (gate >= CCM_LPCG_COUNT) + { + return -EINVAL; + } + + /* Make sure direct mode is on, which is what we support */ + + value = getreg32(IMX9_CCM_LPCG_AUTH(gate)); + if (value & CCM_LPCG_AUTH_CPULPM) + { + value &= ~CCM_LPCG_AUTH_CPULPM; + putreg32(value, IMX9_CCM_LPCG_AUTH(gate)); + mb(); + } + + value = enabled ? 1 : 0; + putreg32(value, IMX9_CCM_LPCG_DIR(gate)); + mb(); + + /* Wait for the clock state change */ + + while ((getreg32(IMX9_CCM_LPCG_STAT0(gate)) & CCM_LPCG_STAT0_ON) != value); + + return OK; +} diff --git a/arch/arm64/src/imx9/imx9_ccm.h b/arch/arm64/src/imx9/imx9_ccm.h new file mode 100644 index 0000000000000..fa2017b314a54 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_ccm.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_ccm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_CCM_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_CCM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Name: imx9_ccm_configure_root_clock + * + * Description: + * Change root clock source and divider. Leaves the clock running state + * unaltered. + * + * Input Parameters: + * root - The root clock index. + * src - The root clock MUX source. + * div - The root clock divider. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int imx9_ccm_configure_root_clock(int root, int src, uint32_t div); + +/**************************************************************************** + * Name: imx9_ccm_root_clock_on + * + * Description: + * Enable / disable root clock. + * + * Input Parameters: + * root - The root clock index. + * enabled - True enables the clock; false disables it. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int imx9_ccm_root_clock_on(int root, bool enabled); + +/**************************************************************************** + * Name: imx9_ccm_gate_on + * + * Description: + * Enable / disable clock. + * + * Input Parameters: + * gate - The clock gate index. + * enabled - True enables the clock; false disables it. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +int imx9_ccm_gate_on(int gate, bool enabled); + +#endif /* __ARCH_ARM64_SRC_IMX9_IMX9_CCM_H */ diff --git a/arch/arm64/src/imx9/imx9_clockconfig.c b/arch/arm64/src/imx9/imx9_clockconfig.c new file mode 100644 index 0000000000000..cc4d87a0b032b --- /dev/null +++ b/arch/arm64/src/imx9/imx9_clockconfig.c @@ -0,0 +1,320 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_clockconfig.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "barriers.h" + +#include "arm64_internal.h" +#include "imx9_ccm.h" +#include "imx9_clockconfig.h" + +#include "hardware/imx9_ccm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define mb() \ + do \ + { \ + ARM64_DSB(); \ + ARM64_ISB(); \ + } \ + while (0) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint32_t g_pll_freqs[] = +{ + [OSC_24M] = 24000000U, /* 24MHZ OSCILLATOR. */ + [ARM_PLL] = 2000000000U, /* ARM PLL */ + [ARM_PLLOUT] = 2000000000U, /* ARM PLL OUT */ + [SYS_PLL1_IN] = 4000000000U, /* SYSTEM PLL1 IN */ + [SYS_PLL1PFD0_IN] = 1000000000U, /* SYSTEM PLL1 PFD0 IN */ + [SYS_PLL1PFD0] = 1000000000U, /* SYSTEM PLL1 PFD0 */ + [SYS_PLL1PFD0DIV2] = 500000000U, /* SYSTEM PLL1 PFD0 DIV2 */ + [SYS_PLL1PFD1_IN] = 800000000U, /* SYSTEM PLL1 PFD1 IN */ + [SYS_PLL1PFD1] = 800000000U, /* SYSTEM PLL1 PFD1 */ + [SYS_PLL1PFD1DIV2] = 400000000U, /* SYSTEM PLL1 PFD1 DIV2 */ + [SYS_PLL1PFD2_IN] = 625000000U, /* SYSTEM PLL1 PFD2 IN */ + [SYS_PLL1PFD2] = 625000000U, /* SYSTEM PLL1 PFD2 */ + [SYS_PLL1PFD2DIV2] = 312500000U, /* SYSTEM PLL1 PFD2 DIV2 */ + [AUDIO_PLL1] = 0U, /* AUDIO PLL1 */ + [AUDIO_PLL1OUT] = 0U, /* AUDIO PLL1 OUT */ + [DRAM_PLL] = 1000000000U, /* DRAM PLL */ + [DRAM_PLLOUT] = 1000000000U, /* DRAM PLL OUT */ + [VIDEO_PLL1] = 0U, /* VIDEO PLL1 */ + [VIDEO_PLL1OUT] = 0U, /* VIDEO PLL1 OUT */ + [EXT] = 0U /* EXT */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_IMX9_PLL + +# error "Missing logic" + +static int pll_init(uintptr_t reg, bool frac, struct pll_parms *parm) +{ + uint32_t val; + + /* Bypass and disable PLL */ + + putreg32(PLL_CTRL_CLKMUX_BYPASS, PLL_SET(PLL_CTRL(reg))); + putreg32(PLL_CTRL_CLKMUX_EN | PLL_CTRL_POWERUP, PLL_CLR(PLL_CTRL(reg))); + + /* Set the integer dividers */ + + val = PLL_DIV_RDIV(parm->rdiv) | + PLL_DIV_MFI(parm->mfi) | + PLL_DIV_ODIV(parm->odiv); + + putreg32(val, PLL_DIV(reg)); + + /* Disable spread spectrum */ + + putreg32(PLL_SPREAD_SPECTRUM_ENABLE, PLL_CLR(PLL_SPREAD_SPECTRUM(reg))); + + /* Set the fractional parts */ + + if (frac) + { + putreg32(PLL_NUMERATOR_MFN(parm->mfn), PLL_NUMERATOR(reg)); + putreg32(PLL_DENOMINATOR_MFD(parm->mfd), PLL_DENOMINATOR(reg)); + } + + /* Power it back up and wait for lock */ + + putreg32(PLL_CTRL_POWERUP, PLL_SET(PLL_CTRL(reg))); + mb(); + + while (!(getreg32(PLL_PLL_STATUS(reg)) & PLL_PLL_STATUS_PLL_LOCK)); + + /* Enable PLL and its output */ + + putreg32(PLL_CTRL_CLKMUX_EN, PLL_SET(PLL_CTRL(reg))); + putreg32(PLL_CTRL_CLKMUX_BYPASS, PLL_CLR(PLL_CTRL(reg))); + mb(); + + return OK; +} + +static int pll_pfd_init(uintptr_t reg, int pfd, struct pfd_parms *pfdparm) +{ + uintptr_t ctrl; + uintptr_t div; + uint32_t val; + + /* Determine the PFD register set */ + + switch (pfd) + { + case 0: + ctrl = PLL_DFS_CTRL_0(reg); + div = PLL_DFS_DIV_0(reg); + break; + + case 1: + ctrl = PLL_DFS_CTRL_1(reg); + div = PLL_DFS_DIV_1(reg); + break; + + case 2: + ctrl = PLL_DFS_CTRL_2(reg); + div = PLL_DFS_DIV_2(reg); + break; + + default: + return -EINVAL; + } + + /* Bypass and disable DFS */ + + putreg32(PLL_DFS_BYPASS_EN, PLL_SET(ctrl)); + putreg32(PLL_DFS_CLKOUT_EN | PLL_DFS_ENABLE, PLL_CLR(ctrl)); + + /* Set the divider */ + + val = PLL_DFS_MFI(pfdparm->mfi) | PLL_DFS_MFN(pfdparm->mfn); + putreg32(val, PLL_SET(div)); + + /* Enable (or disable) the divby2 output */ + + if (pfdparm->divby2_en) + { + putreg32(PLL_DFS_CLKOUT_DIVBY2_EN, PLL_SET(ctrl)); + } + else + { + putreg32(PLL_DFS_CLKOUT_DIVBY2_EN, PLL_CLR(ctrl)); + } + + /* Enable DFS and wait for lock */ + + putreg32(PLL_DFS_ENABLE, PLL_SET(ctrl)); + mb(); + + /* Wait until the clock output is valid */ + + while (!(getreg32(PLL_DFS_STATUS(reg)) & (1 << pfd))); + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_clockconfig + * + * Description: + * Called to initialize the i.IMX9. This does whatever setup is needed to + * put the SoC in a usable state. This includes the initialization of + * clocking using the settings in board.h. + * + ****************************************************************************/ + +void imx9_clockconfig(void) +{ + /* REVISIT: Define a clock config and run it. For now we rely on the fact + * that the boot code + bootloader will have set us up. + * + * During boot the ROM code initializes the PLL clocks as follows: + * + * - OSC24M : 24 MHz + * - ARMPLL : 2000 MHz + * - ARMPLL_OUT : 2000 MHz + * - DRAMPLL : 1000 MHz + * - SYSPLL1 : 4000 MHz + * - SYSPLL_PFD0 : 1000 MHz + * - SYSPLL_PFD1 : 800 MHz + * - SYSPLL_PFD2 : 625 MHz + * - AUDIOPLL : OFF + * - AUDIOPLL_OUT : OFF + * - VIDEOPLL : OFF + * - VIDEOPLL_OUT : OFF + * + * After reset all clock sources (OSCPLL) and root clocks (CLOCK_ROOT) are + * running, but gated (LPCG). + * + * By default, all peripheral root clocks are set to the 24 MHz oscillator. + */ +} + +/**************************************************************************** + * Name: imx9_get_clock + * + * Description: + * This function returns the clock frequency of the specified functional + * clock. + * + * Input Parameters: + * clkname - Identifies the clock of interest + * frequency - The location where the peripheral clock frequency will be + * returned + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. -ENODEV is returned if the clock is not enabled or is not + * being clocked. + * + ****************************************************************************/ + +int imx9_get_clock(int clkname, uint32_t *frequency) +{ + if (clkname >= EXT) + { + *frequency = 0; + return -ENODEV; + } + + *frequency = g_pll_freqs[clkname]; + return OK; +} + +/**************************************************************************** + * Name: imx9_get_rootclock + * + * Description: + * This function returns the clock frequency of the specified root + * functional clock. + * + * Input Parameters: + * clkroot - Identifies the peripheral clock of interest + * frequency - The location where the peripheral clock frequency will be + * returned + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. -ENODEV is returned if the clock is not enabled or is not + * being clocked. + * + ****************************************************************************/ + +int imx9_get_rootclock(int clkroot, uint32_t *frequency) +{ + uint32_t reg; + uint32_t div; + uint32_t mux; + int clk_name; + + if (clkroot <= CCM_CR_COUNT) + { + reg = getreg32(IMX9_CCM_CR_CTRL(clkroot)); + + if ((reg & CCM_CR_CTRL_OFF) == CCM_CR_CTRL_OFF) + { + *frequency = 0; + } + else + { + mux = (reg & CCM_CR_CTRL_MUX_MASK) >> CCM_CR_CTRL_MUX_SHIFT; + clk_name = g_ccm_root_mux[clkroot][mux]; + imx9_get_clock(clk_name, frequency); + div = ((reg & CCM_CR_CTRL_DIV_MASK) >> CCM_CR_CTRL_DIV_SHIFT) + 1; + *frequency = *frequency / div; + } + + return OK; + } + + return -ENODEV; +} diff --git a/arch/arm64/src/imx9/imx9_clockconfig.h b/arch/arm64/src/imx9/imx9_clockconfig.h new file mode 100644 index 0000000000000..90301989a9462 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_clockconfig.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_clockconfig.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_CLOCKCONFIG_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_CLOCKCONFIG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_clockconfig + * + * Description: + * Called to initialize the i.IMX9. This does whatever setup is needed to + * put the SoC in a usable state. This includes the initialization of + * clocking using the settings in board.h. + * + ****************************************************************************/ + +void imx9_clockconfig(void); + +/**************************************************************************** + * Name: imx9_get_clock + * + * Description: + * This function returns the clock frequency of the specified functional + * clock. + * + * Input Parameters: + * clkname - Identifies the clock of interest + * frequency - The location where the peripheral clock frequency will be + * returned + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. -ENODEV is returned if the clock is not enabled or is not + * being clocked. + * + ****************************************************************************/ + +int imx9_get_clock(int clkname, uint32_t *frequency); + +/**************************************************************************** + * Name: imx9_get_rootclock + * + * Description: + * This function returns the clock frequency of the specified root + * functional clock. + * + * Input Parameters: + * clkroot - Identifies the peripheral clock of interest + * frequency - The location where the peripheral clock frequency will be + * returned + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. -ENODEV is returned if the clock is not enabled or is not + * being clocked. + * + ****************************************************************************/ + +int imx9_get_rootclock(int clkroot, uint32_t *frequency); + +#endif /* __ARCH_ARM64_SRC_IMX9_IMX9_CLOCKCONFIG_H */ diff --git a/arch/arm64/src/imx9/imx9_flexio_pwm.c b/arch/arm64/src/imx9/imx9_flexio_pwm.c new file mode 100644 index 0000000000000..1e93a1ffdc45c --- /dev/null +++ b/arch/arm64/src/imx9/imx9_flexio_pwm.c @@ -0,0 +1,755 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_flexio_pwm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "imx9_flexio_pwm.h" +#include "arm64_arch.h" +#include "imx9_ccm.h" +#include "imx9_iomuxc.h" +#include "hardware/imx9_ccm.h" +#include "hardware/imx9_pinmux.h" +#include "hardware/imx9_flexio.h" + +#ifdef CONFIG_IMX9_FLEXIO_PWM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PIN_FOR_TIMER(priv, timer) ((uint8_t)(priv->pins >> (timer * 8))) + +#ifdef CONFIG_IMX9_FLEXIO1_PWM +# if (CONFIG_PWM_NCHANNELS < CONFIG_IMX9_FLEXIO1_PWM_NCHANNELS) +# error CONFIG_PWM_NCHANNELS < CONFIG_IMX9_FLEXIO1_PWM_NCHANNELS +# endif +#endif + +#ifdef CONFIG_IMX9_FLEXIO2_PWM +# if (CONFIG_PWM_NCHANNELS < CONFIG_IMX9_FLEXIO2_PWM_NCHANNELS) +# error CONFIG_PWM_NCHANNELS < CONFIG_IMX9_FLEXIO2_PWM_NCHANNELS +# endif +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the state of one PWM timer */ + +struct imx9_pwmtimer_s +{ + const struct pwm_ops_s *ops; /* PWM operations */ + const flexio_pwm_id_t id; /* PWM_FLEXIO1 or PWM_FLEXIO2 */ + const int nchannels; /* Number of channels used */ + const uintptr_t base; /* The base address of the FLEXIO */ + const uint64_t pins; /* Mapping of timer outputs to flexio outputs */ + const int int_trigger; /* Uses flex-io internal timer for frequency */ + int trigger_ch; /* Trigger channel */ + unsigned frequency; /* Current frequency setting */ + int period; /* PWM period in ticks of functional clock */ +}; + +/**************************************************************************** + * Static Function Prototypes + ****************************************************************************/ + +/* PWM driver methods */ + +static int pwm_setup(struct pwm_lowerhalf_s *dev); +static int pwm_shutdown(struct pwm_lowerhalf_s *dev); + +static int pwm_start(struct pwm_lowerhalf_s *dev, + const struct pwm_info_s *info); + +static int pwm_stop(struct pwm_lowerhalf_s *dev); +static int pwm_ioctl(struct pwm_lowerhalf_s *dev, + int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This is the list of lower half PWM driver methods used by the upper half + * driver + */ + +static const struct pwm_ops_s g_pwmops = +{ + .setup = pwm_setup, + .shutdown = pwm_shutdown, + .start = pwm_start, + .stop = pwm_stop, + .ioctl = pwm_ioctl, +}; + +static struct imx9_pwmtimer_s g_pwmdev[] = +{ +#ifdef CONFIG_IMX9_FLEXIO1_PWM + { + .ops = &g_pwmops, + .id = PWM_FLEXIO1, + .nchannels = CONFIG_IMX9_FLEXIO1_PWM_NCHANNELS, + .base = IMX9_FLEXIO1_BASE, + .pins = CONFIG_IMX9_FLEXIO1_PWM_CHANNEL_PINS, + .int_trigger = 1, + }, +#endif + +#ifdef CONFIG_IMX9_FLEXIO2_PWM + { + .ops = &g_pwmops, + .id = PWM_FLEXIO2, + .nchannels = CONFIG_IMX9_FLEXIO2_PWM_NCHANNELS, + .base = IMX9_FLEXIO2_BASE, + .pins = CONFIG_IMX9_FLEXIO2_PWM_CHANNEL_PINS, + .int_trigger = 1, + }, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: flexio_getreg + * + * Description: + * Read the value of a flex-io register. + * + * Input Parameters: + * priv - A reference to the PWM block + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +static inline uint32_t flexio_getreg(struct imx9_pwmtimer_s *priv, + int offset) +{ + return getreg32(priv->base + offset); +} + +/**************************************************************************** + * Name: flexio_putreg + * + * Description: + * Read the value of an PWM timer register. + * + * Input Parameters: + * priv - A reference to the PWM block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void flexio_putreg(struct imx9_pwmtimer_s *priv, int offset, + uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * Name: flexio_mux + * + * Description: + * Mux the flex-io output pins to pads. The macros FLEXIOn_PWMx_MUX + * need to be defined in the board.h file + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void flexio_mux(void) +{ +#ifdef CONFIG_IMX9_FLEXIO1_PWM + +# ifdef FLEXIO1_PWM0_MUX + imx9_iomux_configure(FLEXIO1_PWM0_MUX); +# endif + +# ifdef FLEXIO1_PWM1_MUX + imx9_iomux_configure(FLEXIO1_PWM1_MUX); +# endif + +# ifdef FLEXIO1_PWM2_MUX + imx9_iomux_configure(FLEXIO1_PWM2_MUX); +# endif + +# ifdef FLEXIO1_PWM3_MUX + imx9_iomux_configure(FLEXIO1_PWM3_MUX); +# endif + +# ifdef FLEXIO1_PWM4_MUX + imx9_iomux_configure(FLEXIO1_PWM4_MUX); +# endif + +# ifdef FLEXIO1_PWM5_MUX + imx9_iomux_configure(FLEXIO1_PWM5_MUX); +# endif + +# ifdef FLEXIO1_PWM6_MUX + imx9_iomux_configure(FLEXIO1_PWM6_MUX); +# endif + +# ifdef FLEXIO1_PWM7_MUX + imx9_iomux_configure(FLEXIO1_PWM7_MUX); +# endif + +#endif + +#ifdef CONFIG_IMX9_FLEXIO2_PWM + +# ifdef FLEXIO2_PWM0_MUX + imx9_iomux_configure(FLEXIO2_PWM0_MUX); +# endif + +# ifdef FLEXIO2_PWM1_MUX + imx9_iomux_configure(FLEXIO2_PWM1_MUX); +# endif + +# ifdef FLEXIO2_PWM2_MUX + imx9_iomux_configure(FLEXIO2_PWM2_MUX); +# endif + +# ifdef FLEXIO2_PWM3_MUX + imx9_iomux_configure(FLEXIO2_PWM3_MUX); +# endif + +# ifdef FLEXIO2_PWM4_MUX + imx9_iomux_configure(FLEXIO2_PWM4_MUX); +# endif + +# ifdef FLEXIO2_PWM5_MUX + imx9_iomux_configure(FLEXIO2_PWM5_MUX); +# endif + +# ifdef FLEXIO2_PWM6_MUX + imx9_iomux_configure(FLEXIO2_PWM6_MUX); +# endif + +# ifdef FLEXIO2_PWM7_MUX + imx9_iomux_configure(FLEXIO2_PWM7_MUX); +# endif + +#endif +} + +/**************************************************************************** + * Name: pwm_init_trigger_timer + * + * Description: + * Initialize the timer trigger, generating the PWM frequency + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * + * Returned Value: + * OK on success, ERROR if the timer initialization fails + * + ****************************************************************************/ + +static int pwm_init_trigger_timer(struct imx9_pwmtimer_s *priv) +{ + uint32_t reg; + int num_timers; + + /* For now, use the last available flexio timer to produce internal + * trigger. This can be later expanded to use external trigger from + * LPIT timer, if one more PWM channel is required + */ + + /* Get parameter register and number of supported timers */ + + reg = flexio_getreg(priv, IMX9_FLEXIO_PARAM_OFFSET); + num_timers = (reg & FLEXIO_PARAM_TIMER_MASK) >> FLEXIO_PARAM_TIMER_SHIFT; + + num_timers--; + if (num_timers < priv->nchannels) + { + pwmerr("PWM%d max channels %d\n", priv->id, num_timers); + return ERROR; + } + + priv->trigger_ch = num_timers; + + return OK; +} + +/**************************************************************************** + * Name: pwm_select_func_clock + * + * Description: + * Select best suitable functional clock for the flexio + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * freq - The requested PWM frequency for this flexio block + * + * Returned Value: + * Zero on success, negated error value on failure + * + ****************************************************************************/ + +static int pwm_select_func_clock(struct imx9_pwmtimer_s *priv, int freq) +{ + const int max_div = 24000000 / 65536 + 1; /* for 1 Hz */ + int div; + uint32_t period; + + if (freq == 0) + { + priv->period = 0; + return 0; + } + + /* Use the 24MHz OSC clock, and find the best divider to get as much + * resolution as possible using 16 bit timer + */ + + for (div = 1; div < max_div; div++) + { + period = 24000000 / div / freq; + if (period < 65536) + { + priv->period = period; + break; + } + } + + imx9_ccm_configure_root_clock(CCM_CR_FLEXIO1 + priv->id, OSC_24M, div); + + /* Enable peripheral clock */ + + imx9_ccm_gate_on(CCM_LPCG_FLEXIO1 + priv->id , true); + + return 0; +} + +/**************************************************************************** + * Name: pwm_update_frequency + * + * Description: + * Initialize the timer trigger, generating the PWM freuency + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * freq - The requested PWM frequency for this flexio block + * + * Returned Value: + * Zero on success, negated error value on failure + * + ****************************************************************************/ + +static int pwm_update_frequency(struct imx9_pwmtimer_s *priv, int freq) +{ + int ret = pwm_select_func_clock(priv, freq); + if (ret < 0) + { + return ret; + } + + /* Configure the timer to produce internal trigger. The following + * setting produces 50/50 pulse where duty cycle is defined by + * TIMCMP: + * + * TIMCFG: + * TIMOUT = 0 Timer output is logic one when enabled and not + * affected by timer reset + * TIMDEC = 0 Decrement counter on FLEXIO clock + * TIMRST = 0x0 Timer never reset + * TIMDIS = 0x0 Timer never disabled + * TIMENA = 0x0 Timer always enabled + * TIMCTL: + * TIMOD = 0x3 Single 16-bit counter + * PINCFG = 0x0 Output pin disabled + * TIMCMP: frequency / 2 + */ + + flexio_putreg(priv, IMX9_FLEXIO_TIMCMP_OFFSET(priv->trigger_ch), + priv->period / 2); + + /* Enable / disable timer */ + + flexio_putreg(priv, IMX9_FLEXIO_TIMCTL_OFFSET(priv->trigger_ch), + freq > 0 ? FLEXIO_TIMCTL_TIMOD(0x3) : + FLEXIO_TIMCTL_TIMOD(0x0)); + + return ret; +} + +/**************************************************************************** + * Name: pwm_update_duty + * + * Description: + * Change the channel duty cycle. + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * channel - Channel to by updated + * duty - New duty cycle as fraction of 65536 + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_update_duty(struct imx9_pwmtimer_s *priv, int pwm_ch, + ub16_t duty16) +{ + uint32_t edge = ub16toi(duty16 * priv->period + b16HALF); + int timer = pwm_ch - 1; /* map pwm ch 1 to timer 0 etc.. */ + uint32_t regval; + + if (pwm_ch == 0 || pwm_ch > priv->nchannels) + { + pwmerr("ERROR: PWM%d has no such channel: %u\n", priv->id, pwm_ch); + return -EINVAL; + } + + /* Now configure the flexio timers in 16-bit counter mode */ + + /* Timers 0-6: + * TIMCFG: + * TIMOUT = 0 Timer output is 1 when enabled and not affected by reset + * TIMDEC = 0 Decrement counter on FLEXIO clock + * TIMRST = 0x0 Timer never reset + * TIMDIS = 0x2 Timer disabled on counter 0 + * TIMENA = 0x6 Timer enabled on Trigger rising edge + * TIMCTL: + * TIMOD = 0x3 single 16-bit counter + * TRGSEL = 4 * trg_ch + 3 timer "trg_ch" trigger output + * TRGSRC = 1 internal trigger + * PINCFG = 0x3 Timer pin output + * PINSEL = timer number + mux conf + * TIMCMP: duty cycle + */ + + /* If this is the first time configuring the PWMs, configure the + * timer fully, otherwise just update the duty cycle + */ + + flexio_putreg(priv, IMX9_FLEXIO_TIMCMP_OFFSET(timer), edge); + + if (priv->frequency == 0) + { + flexio_putreg(priv, IMX9_FLEXIO_TIMCFG_OFFSET(timer), + FLEXIO_TIMCFG_TIMDIS(0x2) | + FLEXIO_TIMCFG_TIMENA(0x6)); + + /* When initially configuring PINCFG=11b, FLEXIO may briefly drive the + * pin low. To avoid this, configure PINCFG=10b along with the rest of + * the control register and then perform a subsequent write to set + * PINCFG=11b + */ + + regval = (FLEXIO_TIMCTL_TIMOD(0x3) | + FLEXIO_TIMCTL_TRGSEL(4 * priv->trigger_ch + 3) | + FLEXIO_TIMCTL_TRGSRC(priv->int_trigger) | + FLEXIO_TIMCTL_PINSEL(PIN_FOR_TIMER(priv, timer))); + + flexio_putreg(priv, IMX9_FLEXIO_TIMCTL_OFFSET(timer), + regval | FLEXIO_TIMCTL_PINCFG(0x2)); + + flexio_putreg(priv, IMX9_FLEXIO_TIMCTL_OFFSET(timer), + regval | FLEXIO_TIMCTL_PINCFG(0x3)); + } + + pwminfo("PWM%d channel %d, p: %d e: %" PRIu32 "\n", priv->id, pwm_ch, + priv->period, edge); + + return 0; +} + +/**************************************************************************** + * Name: pwm_setup + * + * Description: + * This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * It should not, however, output pulses until the start method is called. + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int pwm_setup(struct pwm_lowerhalf_s *dev) +{ + return OK; +} + +/**************************************************************************** + * Name: pwm_shutdown + * + * Description: + * This method is called when the driver is closed. The lower half driver + * stop pulsed output, free any resources, disable the timer hardware, and + * put the system into the lowest possible power usage state + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_shutdown(struct pwm_lowerhalf_s *dev) +{ + /* Make sure that the output has been stopped */ + + pwm_stop(dev); + + return OK; +} + +/**************************************************************************** + * Name: pwm_start + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_start(struct pwm_lowerhalf_s *dev, + const struct pwm_info_s *info) +{ + struct imx9_pwmtimer_s *priv = (struct imx9_pwmtimer_s *)dev; + int ret = OK; + int i; + + if (priv == NULL || info == NULL || info->frequency == 0) + { + return -EINVAL; + } + + /* Set the frequency if not changed */ + + if (info->frequency != priv->frequency) + { + ret = pwm_update_frequency(priv, info->frequency); + } + + /* Handle channel specific setup */ + + for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) + { + if (ret != OK || info->channels[i].channel == -1) + { + break; + } + + ret = pwm_update_duty(priv, info->channels[i].channel, + info->channels[i].duty); + } + + if (ret == OK) + { + priv->frequency = info->frequency; + } + + return ret; +} + +/**************************************************************************** + * Name: pwm_stop + * + * Description: + * Stop the pulsed output and reset the timer resources + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * Assumptions: + * This function is called to stop the pulsed output at anytime. + * + ****************************************************************************/ + +static int pwm_stop(struct pwm_lowerhalf_s *dev) +{ + struct imx9_pwmtimer_s *priv = (struct imx9_pwmtimer_s *)dev; + int i; + + pwminfo("PWM%d stop\n", priv->id); + + /* Check that timer is valid */ + + if (priv == NULL) + { + return -EINVAL; + } + + /* Disable all the channels */ + + for (i = 0; i < priv->nchannels; i++) + { + flexio_putreg(priv, IMX9_FLEXIO_TIMCTL_OFFSET(i), + FLEXIO_TIMCTL_PINCFG(0x2)); + flexio_putreg(priv, IMX9_FLEXIO_TIMCTL_OFFSET(i), 0); + } + + /* Setting frequency to zero disables trigger clock */ + + return pwm_update_frequency(priv, 0); +} + +/**************************************************************************** + * Name: pwm_ioctl + * + * Description: + * Lower-half logic may support platform-specific ioctl commands + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * cmd - The ioctl command + * arg - The argument accompanying the ioctl command + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_ioctl(struct pwm_lowerhalf_s *dev, int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_flexio_pwm_init + * + * Description: + * Initialize flexio blocks to generate EPWM. + * + * Input Parameters: + * pwmid - A number identifying the pwm block. The number of valid + * IDs varies depending on the configuration. + * + * Returned Value: + * On success, a pointer to the lower half PWM driver is + * returned. NULL is returned on any failure. + * + ****************************************************************************/ + +struct pwm_lowerhalf_s *imx9_flexio_pwm_init(flexio_pwm_id_t pwmid) +{ + struct imx9_pwmtimer_s *lower = NULL; + int i; + + for (i = 0; i < sizeof(g_pwmdev) / sizeof(struct imx9_pwmtimer_s); i++) + { + if (pwmid == g_pwmdev[i].id) + { + lower = &g_pwmdev[i]; + break; + } + } + + if (lower) + { + /* IO mux */ + + flexio_mux(); + + /* Reset FlexIO */ + + flexio_putreg(lower, IMX9_FLEXIO_CTRL_OFFSET, FLEXIO_CTRL_SWRST(1)); + + /* Enable FlexIO and de-assert reset */ + + flexio_putreg(lower, IMX9_FLEXIO_CTRL_OFFSET, FLEXIO_CTRL_FLEXEN(1)); + + /* Make sure that FlexIO is enabled and reset is cleared */ + + while (flexio_getreg(lower, IMX9_FLEXIO_CTRL_OFFSET) != + FLEXIO_CTRL_FLEXEN_MASK); + + /* Initialize the trigger timer used for PWM period generation */ + + if (pwm_init_trigger_timer(lower) != OK) + { + /* Disable FlexIO */ + + flexio_putreg(lower, IMX9_FLEXIO_CTRL_OFFSET, 0); + + return NULL; + } + + pwminfo("PWM%d at 0x%" PRIxPTR " configured\n", pwmid, lower->base); + } + else + { + pwmerr("ERROR: No such timer configured %d\n", pwmid); + } + + return (struct pwm_lowerhalf_s *)lower; +} + +#endif diff --git a/arch/arm64/src/imx9/imx9_flexio_pwm.h b/arch/arm64/src/imx9/imx9_flexio_pwm.h new file mode 100644 index 0000000000000..a4b3f8d97d529 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_flexio_pwm.h @@ -0,0 +1,104 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_flexio_pwm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_FLEXIO_PWM_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_FLEXIO_PWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Check if PWM support for any channel is enabled. */ + +#ifdef CONFIG_IMX9_FLEXIO_PWM + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/imx9_flexio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef enum +{ + PWM_FLEXIO1 = 0, + PWM_FLEXIO2 = 1, +} flexio_pwm_id_t; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_flexio_pwm_init + * + * Description: + * Initialize a FLEXIO block for EPWM usage. + * + * Input Parameters: + * pwmid - A number identifying the pwm block. + * + * Returned Value: + * On success, a pointer to the lower half of the PWM driver is + * returned. NULL is returned on any failure. + * + ****************************************************************************/ + +struct pwm_lowerhalf_s *imx9_flexio_pwm_init(flexio_pwm_id_t pwmid); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_IMX9_FLEXIO_PWM */ +#endif /* __ARCH_ARM64_SRC_IMX9_IMX9_FLEXIO_PWM_H */ diff --git a/arch/arm64/src/imx9/imx9_gpio.c b/arch/arm64/src/imx9/imx9_gpio.c new file mode 100644 index 0000000000000..54db67a1469b5 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_gpio.c @@ -0,0 +1,278 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_gpio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include "chip.h" +#include "arm64_internal.h" +#include "imx9_iomuxc.h" +#include "imx9_gpio.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_gpio_dirout + ****************************************************************************/ + +static inline void imx9_gpio_dirout(uint32_t port, uint32_t pin) +{ + uint32_t regval = getreg32(IMX9_GPIO_PDDR(port)); + regval |= GPIO_PIN(pin); + putreg32(regval, IMX9_GPIO_PDDR(port)); +} + +/**************************************************************************** + * Name: imx9_gpio_dirin + ****************************************************************************/ + +static inline void imx9_gpio_dirin(uint32_t port, uint32_t pin) +{ + uint32_t regval = getreg32(IMX9_GPIO_PDDR(port)); + regval &= ~GPIO_PIN(pin); + putreg32(regval, IMX9_GPIO_PDDR(port)); +} + +/**************************************************************************** + * Name: imx9_gpio_setoutput + ****************************************************************************/ + +static void imx9_gpio_setoutput(uint32_t port, uint32_t pin, bool value) +{ + uintptr_t regaddr = IMX9_GPIO_PDOR(port); + uint32_t regval; + + regval = getreg32(regaddr); + if (value) + { + regval |= GPIO_PIN(pin); + } + else + { + regval &= ~GPIO_PIN(pin); + } + + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: imx9_gpio_getpin_status + ****************************************************************************/ + +static inline bool imx9_gpio_get_pinstatus(uint32_t port, uint32_t pin) +{ + uintptr_t regaddr = IMX9_GPIO_PSOR(port); + uint32_t regval; + + regval = getreg32(regaddr); + return ((regval & GPIO_PIN(pin)) != 0); +} + +/**************************************************************************** + * Name: imx9_gpio_getinput + ****************************************************************************/ + +static inline bool imx9_gpio_getinput(uint32_t port, uint32_t pin) +{ + uintptr_t regaddr = IMX9_GPIO_PDIR(port); + uint32_t regval; + + regval = getreg32(regaddr); + return ((regval & GPIO_PIN(pin)) != 0); +} + +/**************************************************************************** + * Name: imx9_gpio_configinput + ****************************************************************************/ + +static int imx9_gpio_configinput(gpio_pinset_t pinset) +{ + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS); + + /* Configure pin as in input */ + + imx9_gpio_dirin(port, pin); + + return OK; +} + +/**************************************************************************** + * Name: imx9_gpio_configoutput + ****************************************************************************/ + +static inline int imx9_gpio_configoutput(gpio_pinset_t pinset) +{ + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + bool value = ((pinset & GPIO_OUTPUT_ONE) != 0); + + DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS); + + /* Set the output value */ + + imx9_gpio_setoutput(port, pin, value); + + /* Convert the configured input GPIO to an output */ + + imx9_gpio_dirout(port, pin); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_config_gpio + * + * Description: + * Configure a GPIO pin based on pin-encoded description of the pin. + * + ****************************************************************************/ + +int imx9_config_gpio(gpio_pinset_t pinset) +{ + irqstate_t flags; + int ret; + + /* Configure the pin as an input initially to avoid any spurious outputs */ + + flags = enter_critical_section(); + + /* Configure based upon the pin mode */ + + switch (pinset & GPIO_MODE_MASK) + { + case GPIO_INPUT: + { + /* Configure the pin as a GPIO input */ + + ret = imx9_gpio_configinput(pinset); + } + break; + + case GPIO_OUTPUT: + { + /* First configure the pin as a GPIO input to avoid output + * glitches. + */ + + ret = imx9_gpio_configinput(pinset); + if (ret >= 0) + { + /* Convert the input to an output */ + + ret = imx9_gpio_configoutput(pinset); + } + } + break; + +#ifdef CONFIG_IMX9_GPIO_IRQ + case GPIO_INTERRUPT: + { + /* Configure the pin as a GPIO input */ + + ret = imx9_gpio_configinput(pinset); + if (ret == OK) + { + ret = imx9_gpioirq_configure(pinset); + } + } + break; +#endif + + default: + ret = -EINVAL; + break; + } + + leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Name: imx9_gpio_write + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void imx9_gpio_write(gpio_pinset_t pinset, bool value) +{ + irqstate_t flags; + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS); + + flags = enter_critical_section(); + imx9_gpio_setoutput(port, pin, value); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: imx9_gpio_read + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool imx9_gpio_read(gpio_pinset_t pinset) +{ + irqstate_t flags; + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + bool value; + + DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS); + + flags = enter_critical_section(); + if ((pinset & (GPIO_OUTPUT)) == (GPIO_OUTPUT)) + { + value = imx9_gpio_get_pinstatus(port, pin); + } + else + { + value = imx9_gpio_getinput(port, pin); + } + + leave_critical_section(flags); + return value; +} diff --git a/arch/arm64/src/imx9/imx9_gpio.h b/arch/arm64/src/imx9/imx9_gpio.h new file mode 100644 index 0000000000000..229d4d635afa0 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_gpio.h @@ -0,0 +1,323 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_GPIO_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "chip.h" +#include "hardware/imx9_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GPIO pinset is a 16-bit word used to configure the GPIO settings. The + * encoding is as follows... + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ENCODING MMVX BEEG GGGP PPPP + * GPIO INPUT 00.. BEEG GGGP PPPP + * INT INPUT 11.. BEEG GGGP PPPP + * GPIO OUTPUT 01V. ...G GGGP PPPP + */ + +/* Input/Output Selection: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * ENCODING MM.. .... .... .... + */ + +#define GPIO_MODE_SHIFT (14) /* Bits 14-15: Pin mode */ +#define GPIO_MODE_MASK (0x3 << GPIO_MODE_SHIFT) +# define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* GPIO input */ +# define GPIO_OUTPUT (1 << GPIO_MODE_SHIFT) /* GPIO output */ +# define GPIO_INTERRUPT (2 << GPIO_MODE_SHIFT) /* Interrupt input */ + +/* Initial Output Value: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * GPIO OUTPUT 01V. .... .... .... + */ + +#define GPIO_OUTPUT_SHIFT (13) /* Bit 13: Initial output */ +#define GPIO_OUTPUT_MASK (0x1 << GPIO_OUTPUT_SHIFT) +# define GPIO_OUTPUT_ZERO (0 << GPIO_OUTPUT_SHIFT) /* Bit 29: 0=Initial output is low */ +# define GPIO_OUTPUT_ONE (1 << GPIO_OUTPUT_SHIFT) /* Bit 29: 1=Initial output is high */ + +/* Interrupt on both edges configuration + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * INT INPUT 11.. B... .... .... + */ + +#define GPIO_INTBOTHCFG_SHIFT (11) /* Bit 11: Interrupt both edges configuration */ +#define GPIO_INTBOTHCFG_MASK (1 << GPIO_INTBOTHCFG_SHIFT) +# define GPIO_INTBOTH_EDGES (1 << GPIO_INTBOTHCFG_SHIFT) + +/* Interrupt edge/level configuration + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * INT INPUT 11.. .EE. .... .... + */ + +#define GPIO_INTCFG_SHIFT (9) /* Bits 9-10: Interrupt edge/level configuration */ +#define GPIO_INTCFG_MASK (0x3 << GPIO_INTCFG_SHIFT) +# define GPIO_INT_LOWLEVEL (0 << GPIO_INTCFG_SHIFT) +# define GPIO_INT_HIGHLEVEL (1 << GPIO_INTCFG_SHIFT) +# define GPIO_INT_RISINGEDGE (2 << GPIO_INTCFG_SHIFT) +# define GPIO_INT_FALLINGEDGE (3 << GPIO_INTCFG_SHIFT) + +/* GPIO Port Number + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * GPIO IN/OUT .... ...G GGG. .... + */ + +#define GPIO_PORT_SHIFT (5) /* Bits 5-8: GPIO port index */ +#define GPIO_PORT_MASK (0xf << GPIO_PORT_SHIFT) +# define GPIO_PORT1 (GPIO1 << GPIO_PORT_SHIFT) /* GPIO1 */ +# define GPIO_PORT2 (GPIO2 << GPIO_PORT_SHIFT) /* GPIO2 */ +# define GPIO_PORT3 (GPIO3 << GPIO_PORT_SHIFT) /* GPIO3 */ +# define GPIO_PORT4 (GPIO4 << GPIO_PORT_SHIFT) /* GPIO4 */ +# define GPIO_PORT5 (GPIO5 << GPIO_PORT_SHIFT) /* GPIO5 */ +# define GPIO_PORT6 (GPIO6 << GPIO_PORT_SHIFT) /* GPIO6 */ +# define GPIO_PORT7 (GPIO7 << GPIO_PORT_SHIFT) /* GPIO7 */ +# define GPIO_PORT8 (GPIO8 << GPIO_PORT_SHIFT) /* GPIO8 */ +# define GPIO_PORT9 (GPIO9 << GPIO_PORT_SHIFT) /* GPIO9 */ +# define GPIO_PORT10 (GPIO10 << GPIO_PORT_SHIFT) /* GPIO10 */ +# define GPIO_PORT11 (GPIO11 << GPIO_PORT_SHIFT) /* GPIO11 */ +# define GPIO_PORT12 (GPIO12 << GPIO_PORT_SHIFT) /* GPIO12 */ +# define GPIO_PORT13 (GPIO13 << GPIO_PORT_SHIFT) /* GPIO13 */ + +/* GPIO Pin Number: + * + * 1111 1100 0000 0000 + * 5432 1098 7654 3210 + * GPIO IN/OUT .... .... ...P PPPP + */ + +#define GPIO_PIN_SHIFT (0) /* Bits 0-4: GPIO pin number */ +#define GPIO_PIN_MASK (0x1f << GPIO_PIN_SHIFT) +# define GPIO_PIN0 (0 << GPIO_PIN_SHIFT) /* Pin 0 */ +# define GPIO_PIN1 (1 << GPIO_PIN_SHIFT) /* Pin 1 */ +# define GPIO_PIN2 (2 << GPIO_PIN_SHIFT) /* Pin 2 */ +# define GPIO_PIN3 (3 << GPIO_PIN_SHIFT) /* Pin 3 */ +# define GPIO_PIN4 (4 << GPIO_PIN_SHIFT) /* Pin 4 */ +# define GPIO_PIN5 (5 << GPIO_PIN_SHIFT) /* Pin 5 */ +# define GPIO_PIN6 (6 << GPIO_PIN_SHIFT) /* Pin 6 */ +# define GPIO_PIN7 (7 << GPIO_PIN_SHIFT) /* Pin 7 */ +# define GPIO_PIN8 (8 << GPIO_PIN_SHIFT) /* Pin 8 */ +# define GPIO_PIN9 (9 << GPIO_PIN_SHIFT) /* Pin 9 */ +# define GPIO_PIN10 (10 << GPIO_PIN_SHIFT) /* Pin 10 */ +# define GPIO_PIN11 (11 << GPIO_PIN_SHIFT) /* Pin 11 */ +# define GPIO_PIN12 (12 << GPIO_PIN_SHIFT) /* Pin 12 */ +# define GPIO_PIN13 (13 << GPIO_PIN_SHIFT) /* Pin 13 */ +# define GPIO_PIN14 (14 << GPIO_PIN_SHIFT) /* Pin 14 */ +# define GPIO_PIN15 (15 << GPIO_PIN_SHIFT) /* Pin 15 */ +# define GPIO_PIN16 (16 << GPIO_PIN_SHIFT) /* Pin 16 */ +# define GPIO_PIN17 (17 << GPIO_PIN_SHIFT) /* Pin 17 */ +# define GPIO_PIN18 (18 << GPIO_PIN_SHIFT) /* Pin 18 */ +# define GPIO_PIN19 (19 << GPIO_PIN_SHIFT) /* Pin 19 */ +# define GPIO_PIN20 (20 << GPIO_PIN_SHIFT) /* Pin 20 */ +# define GPIO_PIN21 (21 << GPIO_PIN_SHIFT) /* Pin 21 */ +# define GPIO_PIN22 (22 << GPIO_PIN_SHIFT) /* Pin 22 */ +# define GPIO_PIN23 (23 << GPIO_PIN_SHIFT) /* Pin 23 */ +# define GPIO_PIN24 (24 << GPIO_PIN_SHIFT) /* Pin 24 */ +# define GPIO_PIN25 (25 << GPIO_PIN_SHIFT) /* Pin 25 */ +# define GPIO_PIN26 (26 << GPIO_PIN_SHIFT) /* Pin 26 */ +# define GPIO_PIN27 (27 << GPIO_PIN_SHIFT) /* Pin 27 */ +# define GPIO_PIN28 (28 << GPIO_PIN_SHIFT) /* Pin 28 */ +# define GPIO_PIN29 (29 << GPIO_PIN_SHIFT) /* Pin 29 */ +# define GPIO_PIN30 (30 << GPIO_PIN_SHIFT) /* Pin 30 */ +# define GPIO_PIN31 (31 << GPIO_PIN_SHIFT) /* Pin 31 */ + +/* Port access via global LUT */ + +#define IMX9_GPIO_BASE(n) g_gpio_base[n] /* Use GPIO1..GPIOn macros as indices */ + +#define IMX9_GPIO_VERID(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_VERID_OFFSET) +#define IMX9_GPIO_PARAM(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PARAM_OFFSET) +#define IMX9_GPIO_LOCK(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_LOCK_OFFSET) +#define IMX9_GPIO_PCNS(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PCNS_OFFSET) +#define IMX9_GPIO_ICNS(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_ICNS_OFFSET) +#define IMX9_GPIO_PCNP(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PCNP_OFFSET) +#define IMX9_GPIO_ICNP(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_ICNP_OFFSET) +#define IMX9_GPIO_PDOR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PDOR_OFFSET) +#define IMX9_GPIO_PSOR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PSOR_OFFSET) +#define IMX9_GPIO_PCOR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PCOR_OFFSET) +#define IMX9_GPIO_PTOR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PTOR_OFFSET) +#define IMX9_GPIO_PDIR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PDIR_OFFSET) +#define IMX9_GPIO_PDDR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PDDR_OFFSET) +#define IMX9_GPIO_PIDR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_PIDR_OFFSET) +#define IMX9_GPIO_GICLR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_GICLR_OFFSET) +#define IMX9_GPIO_GICHR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_GICHR_OFFSET) + +/* Interrupt status flags, these have two channels. Channel is selected by + * setting / clearing ICRN.IRQS bit. + */ + +#define IMX9_GPIO_ISFR0(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_ISFR0_OFFSET) +#define IMX9_GPIO_ISFR1(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_ISFR1_OFFSET) + +/* GPIO PIN[0...31] and ICR[0...31] */ + +#define IMX9_GPIO_P0DR(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_P0DR_OFFSET) +#define IMX9_GPIO_PNDR(n, p) (IMX9_GPIO_P0DR(n) + ((p) * 0x4)) +#define IMX9_GPIO_ICR0(n) (IMX9_GPIO_BASE(n) + IMX9_GPIO_ICR0_OFFSET) +#define IMX9_GPIO_ICRN(n, p) (IMX9_GPIO_ICR0(n) + ((p) * 0x4)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The smallest integer type that can hold the GPIO encoding */ + +typedef uint16_t gpio_pinset_t; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Look-up table that maps GPIO1..GPIOn indexes into GPIO register base + * addresses + */ + +EXTERN const uintptr_t g_gpio_base[]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_gpioirq_initialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + * + ****************************************************************************/ + +#ifdef CONFIG_IMX9_GPIO_IRQ +void imx9_gpioirq_initialize(void); +#else +# define imx9_gpioirq_initialize() +#endif + +/**************************************************************************** + * Name: imx9_config_gpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +int imx9_config_gpio(gpio_pinset_t pinset); + +/**************************************************************************** + * Name: imx9_gpio_write + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void imx9_gpio_write(gpio_pinset_t pinset, bool value); + +/**************************************************************************** + * Name: imx9_gpio_read + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool imx9_gpio_read(gpio_pinset_t pinset); + +/**************************************************************************** + * Name: imx9_gpioirq_configure + * + * Description: + * Configure an interrupt for the specified GPIO pin. + * + ****************************************************************************/ + +#ifdef CONFIG_IMX9_GPIO_IRQ +int imx9_gpioirq_configure(gpio_pinset_t pinset); +#else +# define imx9_gpioirq_configure(pinset) 0 +#endif + +/**************************************************************************** + * Name: imx9_gpioirq_enable + * + * Description: + * Enable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_IMX9_GPIO_IRQ +int imx9_gpioirq_enable(gpio_pinset_t pinset); +#else +# define imx9_gpioirq_enable(pinset) 0 +#endif + +/**************************************************************************** + * Name: imx9_gpioirq_disable + * + * Description: + * Disable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_IMX9_GPIO_IRQ +int imx9_gpioirq_disable(gpio_pinset_t pinset); +#else +# define imx9_gpioirq_disable(pinset) 0 +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ARCH_ARM64_SRC_IMX9_IMX9_GPIO_H */ diff --git a/arch/arm64/src/imx9/imx9_gpiobase.c b/arch/arm64/src/imx9/imx9_gpiobase.c new file mode 100644 index 0000000000000..cf5e1f0ddb117 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_gpiobase.c @@ -0,0 +1,49 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_gpiobase.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "imx9_gpio.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#if defined(CONFIG_ARCH_CHIP_IMX93) +/* Base address for the GPIO memory mapped registers */ + +const uintptr_t g_gpio_base[] = +{ + IMX9_GPIO1_BASE, + IMX9_GPIO2_BASE, + IMX9_GPIO3_BASE, + IMX9_GPIO4_BASE, +}; +#else +# error Unrecognized i.MX9 architecture +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ diff --git a/arch/arm64/src/imx9/imx9_gpioirq.c b/arch/arm64/src/imx9/imx9_gpioirq.c new file mode 100644 index 0000000000000..e8ba83642c54e --- /dev/null +++ b/arch/arm64/src/imx9/imx9_gpioirq.c @@ -0,0 +1,356 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_gpioirq.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "arm64_internal.h" +#include "imx9_gpio.h" + +#ifdef CONFIG_IMX9_GPIO_IRQ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct imx9_portisr_s +{ + struct + { + xcpt_t isr; /* The interrupt service routine */ + void *arg; /* Argument passed to it */ + } + pins[IMX9_GPIO_NPINS]; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct imx9_portisr_s g_isrtab[IMX9_GPIO_NPORTS]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_gpioN_A_B_interrupt + * + * Description: + * GPIO interrupt handlers. + * + ****************************************************************************/ + +static int imx9_gpio_0_15_interrupt(int irq, void *context, void *arg) +{ + uint32_t port = *(uint32_t *)arg; + uint32_t status; + uint32_t pin; + uint32_t regaddr; + + /* Get the pending interrupt indications */ + + regaddr = IMX9_GPIO_ISFR0(port); + status = getreg32(regaddr) & 0x0000ffff; + + /* Decode the pending interrupts */ + + for (pin = 0; pin < 16 && status != 0; pin++) + { + /* Is the IRQ associate with this pin pending? */ + + uint32_t mask = (1 << pin); + if ((status & mask) != 0) + { + struct imx9_portisr_s *isrtab; + + /* Yes, clear the status bit and dispatch the interrupt */ + + putreg32(mask, regaddr); + status &= ~mask; + + /* Get the interrupt table for this port */ + + isrtab = &g_isrtab[port]; + if (isrtab->pins[pin].isr != NULL) + { + /* Run the user handler with the user's argument */ + + isrtab->pins[pin].isr(irq, context, isrtab->pins[pin].arg); + } + } + } + + return OK; +} + +static int imx9_gpio_16_31_interrupt(int irq, void *context, void *arg) +{ + uint32_t port = *(uint32_t *)arg; + uint32_t status; + uint32_t pin; + uint32_t regaddr; + + /* Get the pending interrupt indications */ + + regaddr = IMX9_GPIO_ISFR0(port); + status = getreg32(regaddr) & 0xffff0000; + + /* Decode the pending interrupts */ + + for (pin = 16; pin < 32 && status != 0; pin++) + { + /* Is the IRQ associate with this pin pending? */ + + uint32_t mask = (1 << pin); + if ((status & mask) != 0) + { + struct imx9_portisr_s *isrtab; + + /* Yes, clear the status bit and dispatch the interrupt */ + + putreg32(mask, regaddr); + status &= ~mask; + + /* Get the interrupt table for this port */ + + isrtab = &g_isrtab[port]; + if (isrtab->pins[pin].isr != NULL) + { + /* Run the user handler with the user's argument */ + + isrtab->pins[pin].isr(irq, context, isrtab->pins[pin].arg); + } + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_gpioirq_initialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + * + ****************************************************************************/ + +void imx9_gpioirq_initialize(void) +{ + uint32_t port; + uint32_t pin; + + /* Disable all GPIO interrupts at the source */ + + for (port = 0; port < IMX9_GPIO_NPORTS; port++) + { + for (pin = 0; pin < IMX9_GPIO_NPINS; pin++) + { + /* Reset the interrupt configuration, disabling the interrupt */ + + putreg32(0, IMX9_GPIO_ICRN(port, pin)); + } + } + + /* Disable all unconfigured GPIO interrupts at the NVIC */ + + up_disable_irq(IMX9_IRQ_GPIO1_0_15); + up_disable_irq(IMX9_IRQ_GPIO1_16_31); + + up_disable_irq(IMX9_IRQ_GPIO2_0_15); + up_disable_irq(IMX9_IRQ_GPIO2_16_31); + + up_disable_irq(IMX9_IRQ_GPIO3_0_15); + up_disable_irq(IMX9_IRQ_GPIO3_16_31); + + up_disable_irq(IMX9_IRQ_GPIO4_0_15); + up_disable_irq(IMX9_IRQ_GPIO4_16_31); + + /* Attach all configured GPIO interrupts and enable the interrupt at the + * NVIC + */ + + DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO1_0_15, + imx9_gpio_0_15_interrupt, (void *)1)); + up_enable_irq(IMX9_IRQ_GPIO1_0_15); + DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO1_16_31, + imx9_gpio_16_31_interrupt, (void *)1)); + up_enable_irq(IMX9_IRQ_GPIO1_16_31); + + DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO2_0_15, + imx9_gpio_0_15_interrupt, (void *)2)); + up_enable_irq(IMX9_IRQ_GPIO1_0_15); + DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO2_16_31, + imx9_gpio_16_31_interrupt, (void *)2)); + up_enable_irq(IMX9_IRQ_GPIO1_16_31); + + DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO3_0_15, + imx9_gpio_0_15_interrupt, (void *)3)); + up_enable_irq(IMX9_IRQ_GPIO1_0_15); + DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO3_16_31, + imx9_gpio_16_31_interrupt, (void *)3)); + up_enable_irq(IMX9_IRQ_GPIO1_16_31); + + DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO4_0_15, + imx9_gpio_0_15_interrupt, (void *)4)); + up_enable_irq(IMX9_IRQ_GPIO1_0_15); + DEBUGVERIFY(irq_attach(IMX9_IRQ_GPIO4_16_31, + imx9_gpio_16_31_interrupt, (void *)4)); + up_enable_irq(IMX9_IRQ_GPIO1_16_31); +} + +/**************************************************************************** + * Name: imx9_gpioirq_attach + * + * Description: + * Attach a pin interrupt handler. + * + ****************************************************************************/ + +int imx9_gpioirq_attach(gpio_pinset_t pinset, xcpt_t isr, void *arg) +{ + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + /* Atomically change the handler */ + + irqstate_t flags = enter_critical_section(); + + g_isrtab[port].pins[pin].isr = isr; + g_isrtab[port].pins[pin].arg = arg; + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: imx9_gpioirq_configure + * + * Description: + * Configure an interrupt for the specified GPIO pin. + * + ****************************************************************************/ + +int imx9_gpioirq_configure(gpio_pinset_t pinset) +{ + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + /* Nothing much to do here, just reset the IRQ config */ + + putreg32(0, IMX9_GPIO_ICRN(port, pin)); + + return OK; +} + +/**************************************************************************** + * Name: imx9_gpioirq_enable + * + * Description: + * Enable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +int imx9_gpioirq_enable(gpio_pinset_t pinset) +{ + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + uint32_t icr = (pinset & GPIO_INTCFG_MASK) >> GPIO_INTCFG_SHIFT; + uint32_t both = (pinset & GPIO_INTBOTHCFG_MASK) >> GPIO_INTBOTHCFG_SHIFT; + uint32_t regval; + uintptr_t regaddr; + + /* Perform RMW to the specific pin */ + + regaddr = IMX9_GPIO_ICRN(port, pin); + regval = getreg32(regaddr); + regval &= ~IMX9_GPIO_ICRN_MASK; + + if (both) + { + regval |= IMX9_GPIO_ICRN_BOTH; + } + else if (icr == GPIO_INT_LOWLEVEL) + { + regval |= IMX9_GPIO_ICRN_ZERO; + } + else if (icr == GPIO_INT_HIGHLEVEL) + { + regval |= IMX9_GPIO_ICRN_ONE; + } + else if (icr == GPIO_INT_RISINGEDGE) + { + regval |= IMX9_GPIO_ICRN_RISING; + } + else /* GPIO_INT_FALLINGEDGE */ + { + regval |= IMX9_GPIO_ICRN_FALLING; + } + + putreg32(regval, regaddr); + return OK; +} + +/**************************************************************************** + * Name: imx9_gpioirq_disable + * + * Description: + * Disable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +int imx9_gpioirq_disable(gpio_pinset_t pinset) +{ + uint32_t port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + uint32_t pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + uint32_t regval; + uintptr_t regaddr; + + /* Perform RMW to the specific pin */ + + regaddr = IMX9_GPIO_ICRN(port, pin); + regval = getreg32(regaddr); + regval &= ~IMX9_GPIO_ICRN_MASK; + + putreg32(regval, regaddr); + return OK; +} + +#endif /* CONFIG_IMX9_GPIO_IRQ */ diff --git a/arch/arm64/src/imx9/imx9_iomuxc.c b/arch/arm64/src/imx9/imx9_iomuxc.c new file mode 100644 index 0000000000000..b5f8b657cf996 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_iomuxc.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_iomuxc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "arm64_internal.h" +#include "imx9_iomuxc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_iomux_configure + * + * Description: + * This function writes the encoded pad configuration to the Pad Control + * register. + * + * Input Parameters: + * cfg - The IOMUX configuration + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int imx9_iomux_configure(iomux_cfg_t cfg) +{ + if (!cfg.padcfg.ctlreg) + { + return -EINVAL; + } + + putreg32(cfg.padcfg.mode | cfg.mux, cfg.padcfg.ctlreg); + + if (cfg.padcfg.dsyreg) + { + putreg32(cfg.padcfg.dsy, cfg.padcfg.dsyreg); + } + + if (cfg.padcfg.padreg) + { + putreg32(cfg.pad, cfg.padcfg.padreg); + } + + return OK; +} + +/**************************************************************************** + * Name: imx9_iomux_configure + * + * Description: + * This can be used to forcibly set a pad to GPIO mode. This overrides and + * disconnects any peripheral using the pin. + * + * Input Parameters: + * cfg - The IOMUX configuration. + * sion - if true; sets SION, otherwise clears it. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int imx9_iomux_gpio(iomux_cfg_t cfg, bool sion) +{ + uint32_t reg_sion; + + if (!cfg.padcfg.ctlreg) + { + return -EINVAL; + } + + /* Set sion if requested to do so */ + + reg_sion = sion ? IOMUXC_MUX_SION_ON : 0; + + /* Based on pad number, either ALT0/ALT5 sets the pad as GPIO */ + + if ((cfg.padcfg.ctlreg >= IOMUXC_MUX_CTL_GPIO_IO00_OFFSET) && + (cfg.padcfg.ctlreg <= IOMUXC_MUX_CTL_GPIO_IO29_OFFSET)) + { + putreg32(IOMUXC_MUX_MODE_ALT0 | reg_sion, cfg.padcfg.ctlreg); + } + else + { + putreg32(IOMUXC_MUX_MODE_ALT5 | reg_sion, cfg.padcfg.ctlreg); + } + + return OK; +} diff --git a/arch/arm64/src/imx9/imx9_iomuxc.h b/arch/arm64/src/imx9/imx9_iomuxc.h new file mode 100644 index 0000000000000..80bacc7e5c8d6 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_iomuxc.h @@ -0,0 +1,117 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_iomuxc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "hardware/imx9_iomuxc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define IOMUX_PADCFG(_ctlreg, _mode, _dsyreg, _dsy, _padreg) \ + { \ + .ctlreg = (_ctlreg), \ + .mode = (_mode), \ + .dsyreg = (_dsyreg), \ + .dsy = (_dsy), \ + .padreg = (_padreg), \ + } + +#define IOMUX_CFG(_padcfg, _pad, _mux) \ + (iomux_cfg_t) \ + { \ + .padcfg = _padcfg, \ + .pad = (_pad), \ + .mux = (_mux), \ + } + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Information for the pad alternate function */ + +struct iomux_padcfg_s +{ + /* Register offsets for PAD */ + + uintptr_t ctlreg; + uintptr_t padreg; + uintptr_t dsyreg; + + /* ALT and input daisy configuration for pad */ + + uint32_t mode; + uint32_t dsy; +}; + +struct iomux_cfg_s +{ + struct iomux_padcfg_s padcfg; + + /* Register values */ + + uint32_t pad; + uint32_t mux; +}; +typedef struct iomux_cfg_s iomux_cfg_t; + +/**************************************************************************** + * Name: imx9_iomux_configure + * + * Description: + * This function writes the encoded pad configuration to the Pad Control + * register. + * + * Input Parameters: + * cfg - The IOMUX configuration + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int imx9_iomux_configure(iomux_cfg_t cfg); + +/**************************************************************************** + * Name: imx9_iomux_configure + * + * Description: + * This can be used to forcibly set a pad to GPIO mode. This overrides and + * disconnects any peripheral using the pin. + * + * Input Parameters: + * cfg - The IOMUX configuration. + * sion - if true; sets SION, otherwise clears it. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int imx9_iomux_gpio(iomux_cfg_t cfg, bool sion); diff --git a/arch/arm64/src/imx9/imx9_lpuart.c b/arch/arm64/src/imx9/imx9_lpuart.c new file mode 100644 index 0000000000000..2fa4307f4c259 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_lpuart.c @@ -0,0 +1,950 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_lpuart.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" +#include "arm64_arch.h" +#include "arm64_internal.h" +#include "arm64_gic.h" + +#include "imx9_serial.h" +#include "imx9_boot.h" + +#include "hardware/imx9_lpuart.h" +#include "hardware/imx9_memorymap.h" + +#ifdef USE_SERIALDRIVER + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Which UART with be tty0/console and which tty1-4? The console will + * always be ttyS0. If there is no console then will use the lowest + * numbered UART. + */ + +/* First pick the console and ttys0. This could be any of UART1-5 */ + +#if defined(CONFIG_UART1_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart1port /* UART1 is console */ +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +# define UART1_ASSIGNED 1 +#endif + +/* Rx DMA timeout in ms, which is used to calculate Rx ring buffer size */ +#define DMA_RX_TIMEOUT (10) +#define UART_AUTOSUSPEND_TIMEOUT 3000 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct imx9_uart_port_s +{ + unsigned long iobase; + unsigned int baud; /* Configured baud */ + unsigned int irq_num; + unsigned int txfifo_size; + unsigned int rxfifo_size; + int is_console; +}; + +static inline uint32_t imx9_read(struct imx9_uart_port_s *port, uint32_t off) +{ + return getreg32(port->iobase + off); +} + +static inline void imx9_write(struct imx9_uart_port_s *port, uint32_t val, + uint32_t off) +{ + putreg32(val, port->iobase + off); +} + +static int imx9_lpuart_stop_tx(struct imx9_uart_port_s *sport) +{ + unsigned long temp; + + temp = imx9_read(sport, UARTCTRL); + temp &= ~(UARTCTRL_TIE | UARTCTRL_TCIE); + imx9_write(sport, temp, UARTCTRL); + + return 0; +} + +static int imx9_lpuart_stop_rx(struct imx9_uart_port_s *sport) +{ + unsigned long temp; + + temp = imx9_read(sport, UARTCTRL); + imx9_write(sport, temp & ~UARTCTRL_RE, UARTCTRL); + + return 0; +} + +static int imx9_lpuart_start_tx(struct imx9_uart_port_s *sport) +{ + unsigned long temp; + + temp = imx9_read(sport, UARTCTRL); + imx9_write(sport, temp | UARTCTRL_TIE, UARTCTRL); + + return 0; +} + +static int imx9_lpuart_start_rx(struct imx9_uart_port_s *sport) +{ + unsigned long temp; + + temp = imx9_read(sport, UARTCTRL); + imx9_write(sport, temp | UARTCTRL_RE, UARTCTRL); + + return 0; +} + +/**************************************************************************** + * Name: imx9_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void imx9_rxint(struct uart_dev_s *dev, bool enable) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + + if (enable) + { + imx9_lpuart_start_rx(sport); + } + else + { + imx9_lpuart_stop_rx(sport); + } +} + +/**************************************************************************** + * Name: imx9_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void imx9_txint(struct uart_dev_s *dev, bool enable) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + + if (enable) + { + imx9_lpuart_start_tx(sport); + } + else + { + imx9_lpuart_stop_tx(sport); + } +} + +/**************************************************************************** + * Name: imx9_send + * + * Description: + * This method will send one byte on the UART + * + ****************************************************************************/ + +static void imx9_send(struct uart_dev_s *dev, int ch) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + + imx9_write(sport, ch, UARTDATA); +} + +/**************************************************************************** + * Name: imx9_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the UART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +static int imx9_receive(struct uart_dev_s *dev, unsigned int *status) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + unsigned int rx; + unsigned int sr; + + /* to clear the FE, OR, NF, FE, PE flags, + * read STAT then read DATA reg + */ + + sr = imx9_read(sport, UARTSTAT); + rx = imx9_read(sport, UARTDATA); + + *status = sr; + + return rx; +} + +/**************************************************************************** + * Name: imx9_rxavailable + * + * Description: + * Return true if the receive fifo is not empty + * + ****************************************************************************/ + +static bool imx9_rxavailable(struct uart_dev_s *dev) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + unsigned long sfifo = imx9_read(sport, UARTFIFO); + + if (sfifo & UARTFIFO_RXEMPT) + { + return false; + } + else + { + return true; + } +} + +/**************************************************************************** + * Name: imx9_txready + * + * Description: + * Return true if the tranmsit fifo is not full + * + ****************************************************************************/ + +static bool imx9_txready(struct uart_dev_s *dev) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + unsigned long txcnt; + + /* When TXFULL is set, there is no space in the Tx FIFO */ + + txcnt = imx9_read(sport, UARTWATER); + txcnt = txcnt >> UARTWATER_TXCNT_OFF; + txcnt &= UARTWATER_COUNT_MASK; + + if (txcnt < sport->txfifo_size) + { + return true; + } + else + { + return false; + } +} + +/**************************************************************************** + * Name: imx9_txempty + * + * Description: + * Return true if the transmit fifo is empty + * + ****************************************************************************/ + +static bool imx9_txempty(struct uart_dev_s *dev) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + unsigned long stat = imx9_read(sport, UARTSTAT); + unsigned long sfifo = imx9_read(sport, UARTFIFO); + + if (stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT) + { + return true; + } + else + { + return false; + } +} + +/**************************************************************************** + * Name: imx9_irq_handler (and front-ends) + * + * Description: + * This is the common UART interrupt handler. It should cal + * uart_transmitchars or uart_receivechar to perform the appropriate data + * transfers. + * + ****************************************************************************/ + +static int imx9_uart_irq_handler(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct imx9_uart_port_s *sport; + unsigned long sts; + unsigned long rxcount; + + DEBUGASSERT(dev != NULL && dev->priv != NULL); + sport = (struct imx9_uart_port_s *)dev->priv; + + sts = imx9_read(sport, UARTSTAT); + rxcount = imx9_read(sport, UARTWATER); + rxcount = rxcount >> UARTWATER_RXCNT_OFF; + + if (sts & UARTSTAT_RDRF || rxcount > 0) + { + uart_recvchars(dev); + } + + if (sts & UARTSTAT_TDRE) + { + uart_xmitchars(dev); + } + + imx9_write(sport, sts, UARTSTAT); + return OK; +} + +static int imx9_lpuart_hw_reset(struct imx9_uart_port_s *sport) +{ + if (sport->is_console) + { + return 0; + } + + /* Toggle the reset signal to reset and release the peripheral */ + + putreg32(UARTGLOBAL_RST, sport->iobase + UARTGLOBAL); + putreg32(0, sport->iobase + UARTGLOBAL); + + return 0; +} + +static int imx9_setup(struct uart_dev_s *dev) +{ + irqstate_t i_flags; + int ret; + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + + i_flags = up_irq_save(); + + ret = imx9_lpuart_hw_reset(sport); + if (ret < 0) + { + serr("failed to reset hw: %d\n", ret); + } + + up_irq_restore(i_flags); + + return ret; +} + +/**************************************************************************** + * Name: imx9_shutdown + * + * Description: + * Disable the UART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void imx9_shutdown(struct uart_dev_s *dev) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + unsigned long temp; + irqstate_t i_flags; + + i_flags = up_irq_save(); + + /* clear statue */ + + temp = imx9_read(sport, UARTSTAT); + imx9_write(sport, temp, UARTSTAT); + + /* disable Rx/Tx DMA */ + + temp = imx9_read(sport, UARTBAUD); + temp &= ~(UARTBAUD_TDMAE | UARTBAUD_RDMAE | UARTBAUD_RIDMAE); + imx9_write(sport, temp, UARTBAUD); + + /* disable Rx/Tx and interrupts */ + + temp = imx9_read(sport, UARTCTRL); + temp &= ~(UARTCTRL_TE | UARTCTRL_RE | UARTCTRL_TIE | + UARTCTRL_TCIE | UARTCTRL_RIE | UARTCTRL_ILIE | + UARTCTRL_LOOPS); + imx9_write(sport, temp, UARTCTRL); + imx9_write(sport, 0, UARTMODIR); + + up_irq_restore(i_flags); +} + +static void imx9_setup_watermark(struct imx9_uart_port_s *sport) +{ + unsigned long val; + unsigned long ctrl; + unsigned long ctrl_saved; + unsigned long rxiden_cnt; + + ctrl = imx9_read(sport, UARTCTRL); + ctrl_saved = ctrl; + ctrl &= ~(UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_TE | + UARTCTRL_RIE | UARTCTRL_RE); + imx9_write(sport, ctrl, UARTCTRL); + + /* enable FIFO mode */ + + val = imx9_read(sport, UARTFIFO); + val |= UARTFIFO_TXFE | UARTFIFO_RXFE; + val |= UARTFIFO_TXFLUSH | UARTFIFO_RXFLUSH; + val &= ~(UARTFIFO_RXIDEN_MASK << UARTFIFO_RXIDEN_OFF); + rxiden_cnt = 0; + val |= ((rxiden_cnt & UARTFIFO_RXIDEN_MASK) << UARTFIFO_RXIDEN_OFF); + + imx9_write(sport, val, UARTFIFO); + + /* set the watermark + * rx_watermark = 1; + */ + + val = (1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF); + imx9_write(sport, val, UARTWATER); + + /* Restore cr2 */ + + imx9_write(sport, ctrl_saved, UARTCTRL); +} + +static void imx9_setup_watermark_enable(struct imx9_uart_port_s *sport) +{ + uint32_t temp; + + imx9_setup_watermark(sport); + + temp = imx9_read(sport, UARTCTRL); + temp |= UARTCTRL_RE | UARTCTRL_TE; + temp |= UARTCTRL_IDLECFG << UARTCTRL_IDLECFG_OFF; + imx9_write(sport, temp, UARTCTRL); +} + +static void imx9_hw_disable(struct imx9_uart_port_s *sport) +{ + unsigned long temp; + + temp = imx9_read(sport, UARTCTRL); + temp &= ~(UARTCTRL_RIE | UARTCTRL_ILIE | UARTCTRL_RE | + UARTCTRL_TIE | UARTCTRL_TE); + imx9_write(sport, temp, UARTCTRL); +} + +static void imx9_configure(struct imx9_uart_port_s *sport) +{ + unsigned long temp; + + temp = imx9_read(sport, UARTCTRL); + temp |= UARTCTRL_RIE | UARTCTRL_ILIE; + temp |= UARTCTRL_TIE; + imx9_write(sport, temp, UARTCTRL); +} + +static void imx9_hw_setup(struct imx9_uart_port_s *sport) +{ + irqstate_t i_flags; + + i_flags = up_irq_save(); + + imx9_hw_disable(sport); + + imx9_setup_watermark_enable(sport); + imx9_configure(sport); + up_enable_irq(sport->irq_num); + + up_irq_restore(i_flags); +} + +/**************************************************************************** + * Name: imx9_attach + * + * Description: + * Configure the UART to operation in interrupt driven mode. This method + * is called when the serial port is opened. Normally, this is just after + * the setup() method is called, however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless + * the hardware supports multiple levels of interrupt enabling). The RX + * and TX interrupts are not enabled until the txint() and rxint() methods + * are called. + * + ****************************************************************************/ + +static int imx9_attach(struct uart_dev_s *dev) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + int ret; + unsigned long temp; + + /* determine FIFO size */ + + temp = imx9_read(sport, UARTFIFO); + + sport->txfifo_size = UARTFIFO_DEPTH( + (temp >> UARTFIFO_TXSIZE_OFF) & UARTFIFO_FIFOSIZE_MASK); + sport->rxfifo_size = UARTFIFO_DEPTH( + (temp >> UARTFIFO_RXSIZE_OFF) & UARTFIFO_FIFOSIZE_MASK); + + ret = irq_attach(sport->irq_num, imx9_uart_irq_handler, dev); + + if (ret == OK) + { + imx9_hw_setup(sport); + } + else + { + sinfo("error ret=%d\n", ret); + } + + return ret; +} + +/**************************************************************************** + * Name: imx_detach + * + * Description: + * Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The + * exception is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void imx9_detach(struct uart_dev_s *dev) +{ + struct imx9_uart_port_s *sport = (struct imx9_uart_port_s *)dev->priv; + + up_disable_irq(sport->irq_num); + irq_detach(sport->irq_num); +} + +/**************************************************************************** + * Name: imx9_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * for current imx9 configure. + * + ****************************************************************************/ + +static int imx9_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#if defined(CONFIG_SERIAL_TIOCSERGSTRUCT) || defined(CONFIG_SERIAL_TERMIOS) + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; + irqstate_t flags; +#endif + int ret = OK; + + switch (cmd) + { +#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT + case TIOCSERGSTRUCT: + { + struct imx_uart_s *user = (struct imx_uart_s *)arg; + if (!user) + { + ret = -EINVAL; + } + else + { + memcpy(user, dev, sizeof(struct imx_uart_s)); + } + } + break; +#endif + +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + struct imx_uart_s *priv = (struct imx_uart_s *)dev->priv; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Return parity */ + + termiosp->c_cflag = ((priv->parity != 0) ? PARENB : 0) | + ((priv->parity == 1) ? PARODD : 0); + + /* Return stop bits */ + + termiosp->c_cflag |= (priv->stopbits2) ? CSTOPB : 0; + + /* Return flow control */ + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + termiosp->c_cflag |= ((priv->oflow) ? CCTS_OFLOW : 0); +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + termiosp->c_cflag |= ((priv->iflow) ? CRTS_IFLOW : 0); +#endif + + /* Return baud */ + + cfsetispeed(termiosp, priv->baud); + + /* Return number of bits */ + + switch (priv->bits) + { + case 5: + { + termiosp->c_cflag |= CS5; + break; + } + + case 6: + { + termiosp->c_cflag |= CS6; + break; + } + + case 7: + { + termiosp->c_cflag |= CS7; + break; + } + + default: + case 8: + { + termiosp->c_cflag |= CS8; + break; + } + +#if defined(CS9) + case 9: + { + termiosp->c_cflag |= CS9; + break; + } +#endif + } + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + struct imx_uart_s *priv = (struct imx_uart_s *)dev->priv; + uint32_t baud; + uint32_t ie; + uint8_t parity; + uint8_t nbits; + bool stop2; + + if ((!termiosp) +#ifdef CONFIG_SERIAL_OFLOWCONTROL + || ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0)) +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + || ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0)) +#endif + ) + { + ret = -EINVAL; + break; + } + + /* Decode baud. */ + + ret = OK; + baud = cfgetispeed(termiosp); + + /* Decode number of bits */ + + switch (termiosp->c_cflag & CSIZE) + { + case CS5: + { + nbits = 5; + break; + } + + case CS6: + { + nbits = 6; + break; + } + + case CS7: + { + nbits = 7; + break; + } + + case CS8: + { + nbits = 8; + break; + } + +#if defined(CS9) + case CS9: + { + nbits = 9; + break; + } + +#endif + default: + { + ret = -EINVAL; + break; + } + } + + /* Decode parity */ + + if ((termiosp->c_cflag & PARENB) != 0) + { + parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + parity = 0; + } + + /* Decode stop bits */ + + stop2 = (termiosp->c_cflag & CSTOPB) != 0; + + /* Verify that all settings are valid before committing */ + + if (ret == OK) + { + /* Commit */ + + priv->baud = baud; + priv->parity = parity; + priv->bits = nbits; + priv->stopbits2 = stop2; +#ifdef CONFIG_SERIAL_OFLOWCONTROL + priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0; +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0; +#endif + + /* effect the changes immediately - note that we do not + * implement TCSADRAIN / TCSAFLUSH + */ + + flags = spin_lock_irqsave(NULL); + imx9_disableuartint(priv, &ie); + ret = imx9_setup(dev); + + /* Restore the interrupt state */ + + imx_restoreuartint(priv, ie); + priv->ie = ie; + spin_unlock_irqrestore(NULL, flags); + } + } + break; +#endif /* CONFIG_SERIAL_TERMIOS */ + + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + default: + { + ret = -ENOTTY; + break; + } + } + + return ret; +} + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Serial driver UART operations */ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = imx9_setup, + .shutdown = imx9_shutdown, + .attach = imx9_attach, + .detach = imx9_detach, + .ioctl = imx9_ioctl, + .receive = imx9_receive, + .rxint = imx9_rxint, + .rxavailable = imx9_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = imx9_send, + .txint = imx9_txint, + .txready = imx9_txready, + .txempty = imx9_txempty, +}; + +/* I/O buffers */ + +#ifdef CONFIG_IMX9_UART1 +static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; + +/* This describes the state of the IMX uart1 port. */ + +static struct imx9_uart_port_s g_uart1priv = +{ + .iobase = IMX9_LPUART1_BASE, + .baud = CONFIG_UART1_BAUD, + .irq_num = IMX9_IRQ_LPUART1, + .is_console = 1, +}; + +static struct uart_dev_s g_uart1port = +{ + .recv = + { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; + +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm64_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in + * debug so that the serial console will be available + * during bootup. This must be called before arm64_serialinit. + * + ****************************************************************************/ + +void arm64_earlyserialinit(void) +{ + /* NOTE: This function assumes that low level hardware configuration + * -- including all clocking and pin configuration -- was performed by the + * function imx9_lowsetup() earlier in the boot sequence. + */ + + /* Enable the console UART. The other UARTs will be initialized if and + * when they are first opened. + */ +#ifdef CONSOLE_DEV + CONSOLE_DEV.isconsole = true; + imx9_setup(&CONSOLE_DEV); +#endif +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug + * writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + arm64_lowputc('\r'); + } + + arm64_lowputc((uint8_t)ch); + return ch; +} + +/**************************************************************************** + * Name: arm64_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that imx_earlyserialinit was called previously. + * + ****************************************************************************/ + +void arm64_serialinit(void) +{ + int ret; + + ret = uart_register("/dev/console", &CONSOLE_DEV); + if (ret < 0) + { + sinfo("error at register dev/console, ret =%d\n", ret); + } + + ret = uart_register("/dev/ttyS0", &TTYS0_DEV); + if (ret < 0) + { + sinfo("error at register dev/ttyS0, ret =%d\n", ret); + } +} + +#endif /* USE_SERIALDRIVER */ diff --git a/arch/arm64/src/imx9/imx9_serial.h b/arch/arm64/src/imx9/imx9_serial.h new file mode 100644 index 0000000000000..854c6367aee77 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_serial.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_serial.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_SERIAL_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_SERIAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "arm64_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imx_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before arm_serialinit. + * + ****************************************************************************/ + +#ifdef USE_EARLYSERIALINIT +void imx9_earlyserialinit(void); +#endif + +/**************************************************************************** + * Name: uart_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before arm_serialinit. + * + ****************************************************************************/ + +#if defined(USE_EARLYSERIALINIT) && defined(IMX9_HAVE_UART) +void uart_earlyserialinit(void); +#endif + +/**************************************************************************** + * Name: uart_serialinit + * + * Description: + * Register the UART serial console and serial ports. This assumes that + * uart_earlyserialinit was called previously. + * + ****************************************************************************/ + +#ifdef IMX9_HAVE_UART +void uart_serialinit(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_IMX9_IMX_SERIAL_H */ diff --git a/arch/arm64/src/imx9/imx9_tpm_pwm.c b/arch/arm64/src/imx9/imx9_tpm_pwm.c new file mode 100644 index 0000000000000..8194ac6ea11bd --- /dev/null +++ b/arch/arm64/src/imx9/imx9_tpm_pwm.c @@ -0,0 +1,693 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_tpm_pwm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "arm64_arch.h" +#include "imx9_tpm_pwm.h" +#include "imx9_iomuxc.h" +#include "imx9_ccm.h" + +#include "hardware/imx9_iomuxc.h" +#include "hardware/imx9_pinmux.h" +#include "hardware/imx9_ccm.h" + +#ifdef CONFIG_IMX9_TPM_PWM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CHMUX(priv, x) ((((priv)->chmux) >> (x)) & 0xff) + +/* This is a temporary shortcut to configure TPM1 and TPM3 + * frequencies correctly; they don't have an own root clock + * + * TODO: Determine the frequencies in a more proper way + */ + +#define AON_CLK_FREQ 133333333 +#define WAKEUP_CLK_FREQ 133333333 +#define OSC_24_CLK_FREQ 24000000 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure represents the state of one PWM timer */ + +struct imx9_pwmtimer_s +{ + const struct pwm_ops_s *ops; /* PWM operations */ + const tpm_pwm_id_t id; /* PWM_TPM1...PWM_TPM6 */ + const uintptr_t base; /* The base address of the TPM */ + const int n_channels; /* Number of channels used for TPM block */ + const uint32_t chmux; /* Additional muxing of TPM outputs */ + const int clk; /* Input clock frequency for the TPM */ + uint32_t period; + unsigned frequency; /* Current frequency setting */ +}; + +/**************************************************************************** + * Static Function Prototypes + ****************************************************************************/ + +/* PWM driver methods */ + +static int pwm_setup(struct pwm_lowerhalf_s *dev); +static int pwm_shutdown(struct pwm_lowerhalf_s *dev); + +static int pwm_start(struct pwm_lowerhalf_s *dev, + const struct pwm_info_s *info); + +static int pwm_stop(struct pwm_lowerhalf_s *dev); +static int pwm_ioctl(struct pwm_lowerhalf_s *dev, + int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* This is the list of lower half PWM driver methods used by the upper half + * driver + */ + +static const struct pwm_ops_s g_pwmops = +{ + .setup = pwm_setup, + .shutdown = pwm_shutdown, + .start = pwm_start, + .stop = pwm_stop, + .ioctl = pwm_ioctl, +}; + +static struct imx9_pwmtimer_s g_pwmdev[] = +{ +#ifdef CONFIG_IMX9_TPM1_PWM + { + .ops = &g_pwmops, + .id = PWM_TPM1, + .base = IMX9_TPM1_BASE, + .n_channels = CONFIG_IMX9_TPM1_PWM_NCHANNELS, + .chmux = CONFIG_IMX9_TPM1_PWM_CHMUX, + .clk = AON_CLK_FREQ, + }, +#endif + +#ifdef CONFIG_IMX9_TPM2_PWM + { + .ops = &g_pwmops, + .id = PWM_TPM2, + .base = IMX9_TPM2_BASE, + .n_channels = CONFIG_IMX9_TPM2_PWM_NCHANNELS, + .chmux = CONFIG_IMX9_TPM2_PWM_CHMUX, + .clk = OSC_24_CLK_FREQ, + }, +#endif + +#ifdef CONFIG_IMX9_TPM3_PWM + { + .ops = &g_pwmops, + .id = PWM_TPM3, + .base = IMX9_TPM3_BASE, + .n_channels = CONFIG_IMX9_TPM3_PWM_NCHANNELS, + .chmux = CONFIG_IMX9_TPM3_PWM_CHMUX, + .clk = WAKEUP_CLK_FREQ, + }, +#endif + +#ifdef CONFIG_IMX9_TPM4_PWM + { + .ops = &g_pwmops, + .id = PWM_TPM4, + .base = IMX9_TPM4_BASE, + .n_channels = CONFIG_IMX9_TPM4_PWM_NCHANNELS, + .chmux = CONFIG_IMX9_TPM4_PWM_CHMUX, + .clk = OSC_24_CLK_FREQ, + }, +#endif + +#ifdef CONFIG_IMX9_TPM5_PWM + { + .ops = &g_pwmops, + .id = PWM_TPM5, + .base = IMX9_TPM5_BASE, + .n_channels = CONFIG_IMX9_TPM5_PWM_NCHANNELS, + .chmux = CONFIG_IMX9_TPM5_PWM_CHMUX, + .clk = OSC_24_CLK_FREQ, + }, +#endif + +#ifdef CONFIG_IMX9_TPM6_PWM + { + .ops = &g_pwmops, + .id = PWM_TPM6, + .base = IMX9_TPM6_BASE, + .n_channels = CONFIG_IMX9_TPM6_PWM_NCHANNELS, + .chmux = CONFIG_IMX9_TPM6_PWM_CHMUX, + .clk = OSC_24_CLK_FREQ, + }, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pwm_getreg + * + * Description: + * Read the value of an PWM timer register. + * + * Input Parameters: + * priv - A reference to the PWM block status + * offset - The offset to the register to read + * + * Returned Value: + * The current contents of the specified register + * + ****************************************************************************/ + +static inline uint32_t pwm_getreg(struct imx9_pwmtimer_s *priv, int offset) +{ + return getreg32(priv->base + offset); +} + +/**************************************************************************** + * Name: pwm_putreg + * + * Description: + * Read the value of an PWM timer register. + * + * Input Parameters: + * priv - A reference to the PWM block status + * offset - The offset to the register to read + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void pwm_putreg(struct imx9_pwmtimer_s *priv, int offset, + uint32_t value) +{ + putreg32(value, priv->base + offset); +} + +/**************************************************************************** + * Name: tpm_mux + * + * Description: + * Mux the tpm output pins to pads. The macros TPMn_PWMx_MUX + * need to be defined in the board.h file + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void tpm_mux(void) +{ +#ifdef CONFIG_IMX9_TPM1_PWM +# ifdef TPM1_PWM0_MUX + imx9_iomux_configure(TPM1_PWM0_MUX); +# endif + +# ifdef TPM1_PWM1_MUX + imx9_iomux_configure(TPM1_PWM1_MUX); +# endif + +# ifdef TPM1_PWM2_MUX + imx9_iomux_configure(TPM1_PWM2_MUX); +# endif + +# ifdef TPM1_PWM3_MUX + imx9_iomux_configure(TPM1_PWM3_MUX); +# endif +#endif + +#ifdef CONFIG_IMX9_TPM2_PWM +# ifdef TPM2_PWM0_MUX + imx9_iomux_configure(TPM2_PWM0_MUX); +# endif + +# ifdef TPM2_PWM1_MUX + imx9_iomux_configure(TPM2_PWM1_MUX); +# endif + +# ifdef TPM2_PWM2_MUX + imx9_iomux_configure(TPM2_PWM2_MUX); +# endif + +# ifdef TPM2_PWM3_MUX + imx9_iomux_configure(TPM2_PWM3_MUX); +# endif +#endif + +#ifdef CONFIG_IMX9_TPM3_PWM +# ifdef TPM3_PWM0_MUX + imx9_iomux_configure(TPM3_PWM0_MUX); +# endif + +# ifdef TPM3_PWM1_MUX + imx9_iomux_configure(TPM3_PWM1_MUX); +# endif + +# ifdef TPM3_PWM2_MUX + imx9_iomux_configure(TPM3_PWM2_MUX); +# endif + +# ifdef TPM3_PWM3_MUX + imx9_iomux_configure(TPM3_PWM3_MUX); +# endif +#endif + +#ifdef CONFIG_IMX9_TPM4_PWM +# ifdef TPM4_PWM0_MUX + imx9_iomux_configure(TPM4_PWM0_MUX); +# endif + +# ifdef TPM4_PWM1_MUX + imx9_iomux_configure(TPM4_PWM1_MUX); +# endif + +# ifdef TPM4_PWM2_MUX + imx9_iomux_configure(TPM4_PWM2_MUX); +# endif + +# ifdef TPM4_PWM3_MUX + imx9_iomux_configure(TPM4_PWM3_MUX); +# endif +#endif + +#ifdef CONFIG_IMX9_TPM5_PWM +# ifdef TPM5_PWM0_MUX + imx9_iomux_configure(TPM5_PWM0_MUX); +# endif + +# ifdef TPM5_PWM1_MUX + imx9_iomux_configure(TPM5_PWM1_MUX); +# endif + +# ifdef TPM5_PWM2_MUX + imx9_iomux_configure(TPM5_PWM2_MUX); +# endif + +# ifdef TPM5_PWM3_MUX + imx9_iomux_configure(TPM5_PWM3_MUX); +# endif +#endif + +#ifdef CONFIG_IMX9_TPM6_PWM +# ifdef TPM6_PWM0_MUX + imx9_iomux_configure(TPM6_PWM0_MUX); +# endif + +# ifdef TPM6_PWM1_MUX + imx9_iomux_configure(TPM6_PWM1_MUX); +# endif + +# ifdef TPM6_PWM2_MUX + imx9_iomux_configure(TPM6_PWM2_MUX); +# endif + +# ifdef TPM6_PWM3_MUX + imx9_iomux_configure(TPM6_PWM3_MUX); +# endif +#endif +} + +/**************************************************************************** + * Name: pwm_update_frequency + * + * Description: + * Initialize the timer trigger, generating the PWM freuency + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * freq - The requested PWM frequency for this flexio block + * + * Returned Value: + * Zero on success, negated error value on failure + * + ****************************************************************************/ + +static int pwm_update_frequency(struct imx9_pwmtimer_s *priv, int freq) +{ + int i; + + if (freq != priv->frequency) + { + /* Start PWM on all channels if it was previously stopped */ + + if (freq > 0 && priv->frequency == 0) + { + /* Set the EPWM mode for all the configured channels: + * + * High-true pulses (clear output on counter match, set output + * on counter reload, clear output when counter first enabled + * or paused) + * SC[CPWMS] = 0, MSnB:MSnA = 1:0 ELSnB:ELSnA = 0 + */ + + for (i = 0; i < priv->n_channels; i++) + { + pwm_putreg(priv, IMX9_TPM_CXSC_OFFSET(CHMUX(priv, i)), + TPM_CXSC_MSB_MASK); + } + } + + priv->period = freq > 0 ? priv->clk / freq : 0; + + pwminfo("PWM%d frequency: %" PRIu32" period: %" PRIu32 "\n", priv->id, + freq, priv->period); + + /* Set the period */ + + pwm_putreg(priv, IMX9_TPM_MOD_OFFSET, priv->period); + + priv->frequency = freq; + } + + return OK; +} + +/**************************************************************************** + * Name: pwm_update_duty + * + * Description: + * Change the channel duty cycle. + * + * Input Parameters: + * priv - A reference to the lower half PWM driver state structure + * period - PWM pulse width in timer ticks + * channel - Channel to by updated + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_update_duty(struct imx9_pwmtimer_s *priv, int pwm_ch, + ub16_t duty16) +{ + uint64_t duty = duty16 & 0xffffffff; + uint32_t edge = (duty * priv->period + 0x8000) >> 16; + int timer = pwm_ch - 1; + + if (pwm_ch == 0 || timer > priv->n_channels) + { + pwmerr("ERROR: PWM%d has no such channel: %d\n", priv->id, timer); + return -EINVAL; + } + + pwminfo("PWM%d channel %d, p: %d e: %" PRIu32 "\n", priv->id, + CHMUX(priv, timer), priv->period, edge); + + pwm_putreg(priv, IMX9_TPM_CXV_OFFSET(CHMUX(priv, timer)), edge); + + return OK; +} + +/**************************************************************************** + * Name: pwm_setup + * + * Description: + * This method is called when the driver is opened. The lower half driver + * should configure and initialize the device so that it is ready for use. + * It should not, however, output pulses until the start method is called. + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int pwm_setup(struct pwm_lowerhalf_s *dev) +{ + return OK; +} + +/**************************************************************************** + * Name: pwm_shutdown + * + * Description: + * This method is called when the driver is closed. The lower half driver + * stop pulsed output, free any resources, disable the timer hardware, and + * put the system into the lowest possible power usage state + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_shutdown(struct pwm_lowerhalf_s *dev) +{ + /* Make sure that the output has been stopped */ + + pwm_stop(dev); + + return OK; +} + +/**************************************************************************** + * Name: pwm_start + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * info - A reference to the characteristics of the pulsed output + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_start(struct pwm_lowerhalf_s *dev, + const struct pwm_info_s *info) +{ + struct imx9_pwmtimer_s *priv = (struct imx9_pwmtimer_s *)dev; + int ret = OK; + int i; + + if (priv == NULL || info == NULL || info->frequency == 0) + { + return -EINVAL; + } + + /* Set the frequency if not changed */ + + if (pwm_update_frequency(priv, info->frequency) == OK) + { + /* Handle channel specific setup */ + + for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) + { + if (ret != OK || info->channels[i].channel == -1) + { + break; + } + + pwm_update_duty(priv, info->channels[i].channel, + info->channels[i].duty); + } + } + + return ret; +} + +/**************************************************************************** + * Name: pwm_stop + * + * Description: + * Stop the pulsed output and reset the timer resources + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + * Assumptions: + * This function is called to stop the pulsed output at anytime. + * + ****************************************************************************/ + +static int pwm_stop(struct pwm_lowerhalf_s *dev) +{ + struct imx9_pwmtimer_s *priv = (struct imx9_pwmtimer_s *)dev; + int i; + + pwminfo("PWM%d stop\n", priv->id); + + /* Check that timer is valid */ + + if (priv == NULL) + { + return -EINVAL; + } + + /* Disable the channels */ + + for (i = 0; i < priv->n_channels; i++) + { + pwm_putreg(priv, IMX9_TPM_CXSC_OFFSET(CHMUX(priv, i)), 0); + } + + /* Set frequency to 0 */ + + pwm_update_frequency(priv, 0); + + return OK; +} + +/**************************************************************************** + * Name: pwm_ioctl + * + * Description: + * Lower-half logic may support platform-specific ioctl commands + * + * Input Parameters: + * dev - A reference to the lower half PWM driver state structure + * cmd - The ioctl command + * arg - The argument accompanying the ioctl command + * + * Returned Value: + * Zero on success; a negated errno value on failure + * + ****************************************************************************/ + +static int pwm_ioctl(struct pwm_lowerhalf_s *dev, int cmd, + unsigned long arg) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_tpm_pwm_init + * + * Description: + * Initialize tpm blocks to generate EPWM. + * + * Input Parameters: + * pwmid - A number identifying the pwm block. The number of valid + * IDs varies depending on the configuration. + * + * Returned Value: + * On success, a pointer to the lower half PWM driver is + * returned. NULL is returned on any failure. + * + ****************************************************************************/ + +struct pwm_lowerhalf_s *imx9_tpm_pwm_init(tpm_pwm_id_t pwmid) +{ + struct imx9_pwmtimer_s *lower = NULL; + int i; + + for (i = 0; i < sizeof(g_pwmdev) / sizeof(g_pwmdev[0]); i++) + { + if (pwmid == g_pwmdev[i].id) + { + lower = &g_pwmdev[i]; + break; + } + } + + if (lower) + { + /* IO mux */ + + tpm_mux(); + + /* Reset TPM */ + + pwm_putreg(lower, IMX9_TPM_GLOBAL_OFFSET, TPM_GLOBAL_RST_MASK); + pwm_putreg(lower, IMX9_TPM_GLOBAL_OFFSET, 0); + while (pwm_getreg(lower, IMX9_TPM_GLOBAL_OFFSET) != 0); + + /* TPM 1 is always clocked by AON bus and TPM3 by WAKEUP bus */ + + if (pwmid != PWM_TPM1 && pwmid != PWM_TPM3) + { + /* 24 MHz source clock */ + + imx9_ccm_configure_root_clock(CCM_CR_TPM1 + pwmid, OSC_24M, 1); + + /* Enable peripheral clock */ + + imx9_ccm_gate_on(CCM_LPCG_TPM1 + pwmid, true); + } + + /* Set status and control: + * CMOD = 1 (increment on every clock) + * PS = 0 (clock divider 1) + */ + + pwm_putreg(lower, IMX9_TPM_SC_OFFSET, 1 << TPM_SC_CMOD_SHIFT); + + pwminfo("PWM%d at %" PRIxPTR " configured\n", pwmid, lower->base); + } + else + { + pwmerr("ERROR: No such timer configured %d\n", pwmid); + } + + return (struct pwm_lowerhalf_s *)lower; +} + +#endif diff --git a/arch/arm64/src/imx9/imx9_tpm_pwm.h b/arch/arm64/src/imx9/imx9_tpm_pwm.h new file mode 100644 index 0000000000000..f6bdfde28e701 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_tpm_pwm.h @@ -0,0 +1,97 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_tpm_pwm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_TPM_PWM_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_TPM_PWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "hardware/imx9_tpm.h" + +/* Check if PWM support for any channel is enabled. */ + +#ifdef CONFIG_IMX9_TPM_PWM + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef enum +{ + PWM_TPM1 = 0, + PWM_TPM2 = 1, + PWM_TPM3 = 2, + PWM_TPM4 = 3, + PWM_TPM5 = 4, + PWM_TPM6 = 5, +} tpm_pwm_id_t; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_tpm_pwm_init + * + * Description: + * Initialize a TPM block for EPWM usage. + * + * Input Parameters: + * pwmid - A number identifying the pwm block. + * + * Returned Value: + * On success, a pointer to the lower half of the PWM driver is + * returned. NULL is returned on any failure. + * + ****************************************************************************/ + +struct pwm_lowerhalf_s *imx9_tpm_pwm_init(tpm_pwm_id_t pwmid); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_IMX9_TPM_PWM */ +#endif /* __ARCH_ARM64_SRC_IMX9_IMX9_TPM_PWM_H */ diff --git a/arch/arm64/src/imx9/imx9_usbdev.c b/arch/arm64/src/imx9/imx9_usbdev.c new file mode 100644 index 0000000000000..30f9fef33f785 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_usbdev.c @@ -0,0 +1,3111 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_usbdev.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "chip.h" +#include "arm64_internal.h" +#include "imx9_ccm.h" +#include "hardware/imx9_memorymap.h" +#include "hardware/imx9_usbotg.h" +#include "hardware/imx9_ccm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_USBDEV_EP0_MAXSIZE +# define CONFIG_USBDEV_EP0_MAXSIZE 64 +#endif + +#ifndef CONFIG_USBDEV_MAXPOWER +# define CONFIG_USBDEV_MAXPOWER 100 /* mA */ +#endif + +/* Enable reading SOF from interrupt handler vs. simply reading on demand. + * Probably a bad idea... Unless there is some issue with sampling the SOF + * from hardware asynchronously. + */ + +#ifdef CONFIG_IMX9_USB_FRAME_INTERRUPT +# define USB_FRAME_INT USBDEV_USBINTR_SRE +#else +# define USB_FRAME_INT 0 +#endif + +#ifdef CONFIG_DEBUG_FEATURES +# define USB_ERROR_INT USBDEV_USBINTR_UEE +#else +# define USB_ERROR_INT 0 +#endif + +/* Debug ********************************************************************/ + +/* Trace error codes */ + +#define IMX9_TRACEERR_ALLOCFAIL 0x0001 +#define IMX9_TRACEERR_BADCLEARFEATURE 0x0002 +#define IMX9_TRACEERR_BADDEVGETSTATUS 0x0003 +#define IMX9_TRACEERR_BADEPNO 0x0004 +#define IMX9_TRACEERR_BADEPGETSTATUS 0x0005 +#define IMX9_TRACEERR_BADEPTYPE 0x0006 +#define IMX9_TRACEERR_BADGETCONFIG 0x0007 +#define IMX9_TRACEERR_BADGETSETDESC 0x0008 +#define IMX9_TRACEERR_BADGETSTATUS 0x0009 +#define IMX9_TRACEERR_BADSETADDRESS 0x000a +#define IMX9_TRACEERR_BADSETCONFIG 0x000b +#define IMX9_TRACEERR_BADSETFEATURE 0x000c +#define IMX9_TRACEERR_BINDFAILED 0x000d +#define IMX9_TRACEERR_DISPATCHSTALL 0x000e +#define IMX9_TRACEERR_DRIVER 0x000f +#define IMX9_TRACEERR_DRIVERREGISTERED 0x0010 +#define IMX9_TRACEERR_EP0SETUPSTALLED 0x0011 +#define IMX9_TRACEERR_EPINNULLPACKET 0x0012 +#define IMX9_TRACEERR_EPOUTNULLPACKET 0x0013 +#define IMX9_TRACEERR_INVALIDCTRLREQ 0x0014 +#define IMX9_TRACEERR_INVALIDPARMS 0x0015 +#define IMX9_TRACEERR_IRQREGISTRATION 0x0016 +#define IMX9_TRACEERR_NOEP 0x0017 +#define IMX9_TRACEERR_NOTCONFIGURED 0x0018 +#define IMX9_TRACEERR_REQABORTED 0x0019 + +/* Trace interrupt codes */ + +#define IMX9_TRACEINTID_USB 0x0001 +#define IMX9_TRACEINTID_CLEARFEATURE 0x0002 +#define IMX9_TRACEINTID_DEVGETSTATUS 0x0003 +#define IMX9_TRACEINTID_DEVRESET 0x0004 +#define IMX9_TRACEINTID_DISPATCH 0x0005 +#define IMX9_TRACEINTID_EP0COMPLETE 0x0006 +#define IMX9_TRACEINTID_EP0NAK 0x0007 +#define IMX9_TRACEINTID_EP0SETUP 0x0008 +#define IMX9_TRACEINTID_EPGETSTATUS 0x0009 +#define IMX9_TRACEINTID_EPIN 0x000a +#define IMX9_TRACEINTID_EPINQEMPTY 0x000b +#define IMX9_TRACEINTID_EP0INSETADDRESS 0x000c +#define IMX9_TRACEINTID_EPOUT 0x000d +#define IMX9_TRACEINTID_EPOUTQEMPTY 0x000e +#define IMX9_TRACEINTID_EP0SETUPSETADDRESS 0x000f +#define IMX9_TRACEINTID_FRAME 0x0010 +#define IMX9_TRACEINTID_GETCONFIG 0x0011 +#define IMX9_TRACEINTID_GETSETDESC 0x0012 +#define IMX9_TRACEINTID_GETSETIF 0x0013 +#define IMX9_TRACEINTID_GETSTATUS 0x0014 +#define IMX9_TRACEINTID_IFGETSTATUS 0x0015 +#define IMX9_TRACEINTID_SETCONFIG 0x0016 +#define IMX9_TRACEINTID_SETFEATURE 0x0017 +#define IMX9_TRACEINTID_SUSPENDED 0x0018 +#define IMX9_TRACEINTID_RESUMED 0x0019 +#define IMX9_TRACEINTID_SYNCHFRAME 0x001a + +#ifdef CONFIG_USBDEV_TRACE_STRINGS +const struct trace_msg_t g_usb_trace_strings_deverror[] = +{ + TRACE_STR(IMX9_TRACEERR_ALLOCFAIL), + TRACE_STR(IMX9_TRACEERR_BADCLEARFEATURE), + TRACE_STR(IMX9_TRACEERR_BADDEVGETSTATUS), + TRACE_STR(IMX9_TRACEERR_BADEPNO), + TRACE_STR(IMX9_TRACEERR_BADEPGETSTATUS), + TRACE_STR(IMX9_TRACEERR_BADEPTYPE), + TRACE_STR(IMX9_TRACEERR_BADGETCONFIG), + TRACE_STR(IMX9_TRACEERR_BADGETSETDESC), + TRACE_STR(IMX9_TRACEERR_BADGETSTATUS), + TRACE_STR(IMX9_TRACEERR_BADSETADDRESS), + TRACE_STR(IMX9_TRACEERR_BADSETCONFIG), + TRACE_STR(IMX9_TRACEERR_BADSETFEATURE), + TRACE_STR(IMX9_TRACEERR_BINDFAILED), + TRACE_STR(IMX9_TRACEERR_DISPATCHSTALL), + TRACE_STR(IMX9_TRACEERR_DRIVER), + TRACE_STR(IMX9_TRACEERR_DRIVERREGISTERED), + TRACE_STR(IMX9_TRACEERR_EP0SETUPSTALLED), + TRACE_STR(IMX9_TRACEERR_EPINNULLPACKET), + TRACE_STR(IMX9_TRACEERR_EPOUTNULLPACKET), + TRACE_STR(IMX9_TRACEERR_INVALIDCTRLREQ), + TRACE_STR(IMX9_TRACEERR_INVALIDPARMS), + TRACE_STR(IMX9_TRACEERR_IRQREGISTRATION), + TRACE_STR(IMX9_TRACEERR_NOEP), + TRACE_STR(IMX9_TRACEERR_NOTCONFIGURED), + TRACE_STR(IMX9_TRACEERR_REQABORTED), + TRACE_STR_END +}; + +const struct trace_msg_t g_usb_trace_strings_intdecode[] = +{ + TRACE_STR(IMX9_TRACEINTID_USB), + TRACE_STR(IMX9_TRACEINTID_CLEARFEATURE), + TRACE_STR(IMX9_TRACEINTID_DEVGETSTATUS), + TRACE_STR(IMX9_TRACEINTID_DEVRESET), + TRACE_STR(IMX9_TRACEINTID_DISPATCH), + TRACE_STR(IMX9_TRACEINTID_EP0COMPLETE), + TRACE_STR(IMX9_TRACEINTID_EP0NAK), + TRACE_STR(IMX9_TRACEINTID_EP0SETUP), + TRACE_STR(IMX9_TRACEINTID_EPGETSTATUS), + TRACE_STR(IMX9_TRACEINTID_EPIN), + TRACE_STR(IMX9_TRACEINTID_EPINQEMPTY), + TRACE_STR(IMX9_TRACEINTID_EP0INSETADDRESS), + TRACE_STR(IMX9_TRACEINTID_EPOUT), + TRACE_STR(IMX9_TRACEINTID_EPOUTQEMPTY), + TRACE_STR(IMX9_TRACEINTID_EP0SETUPSETADDRESS), + TRACE_STR(IMX9_TRACEINTID_FRAME), + TRACE_STR(IMX9_TRACEINTID_GETCONFIG), + TRACE_STR(IMX9_TRACEINTID_GETSETDESC), + TRACE_STR(IMX9_TRACEINTID_GETSETIF), + TRACE_STR(IMX9_TRACEINTID_GETSTATUS), + TRACE_STR(IMX9_TRACEINTID_IFGETSTATUS), + TRACE_STR(IMX9_TRACEINTID_SETCONFIG), + TRACE_STR(IMX9_TRACEINTID_SETFEATURE), + TRACE_STR(IMX9_TRACEINTID_SUSPENDED), + TRACE_STR(IMX9_TRACEINTID_RESUMED), + TRACE_STR(IMX9_TRACEINTID_SYNCHFRAME), + TRACE_STR_END +}; +#endif + +#if defined(CONFIG_ARMV7M_DCACHE) +# define cache_aligned_alloc(s) kmm_memalign(ARMV7M_DCACHE_LINESIZE,(s)) +# define CACHE_ALIGNED_DATA aligned_data(ARMV7M_DCACHE_LINESIZE) +#else +# define cache_aligned_alloc kmm_malloc +# define CACHE_ALIGNED_DATA +#endif + +/* Hardware interface *******************************************************/ + +/* This represents a Endpoint Transfer Descriptor - note these must be 32 + * byte aligned. + */ + +struct imx9_dtd_s +{ + volatile uint32_t nextdesc; /* Address of the next DMA descripto in RAM */ + volatile uint32_t config; /* Misc. bit encoded configuration information */ + uint32_t buffer0; /* Buffer start address */ + uint32_t buffer1; /* Buffer start address */ + uint32_t buffer2; /* Buffer start address */ + uint32_t buffer3; /* Buffer start address */ + uint32_t buffer4; /* Buffer start address */ + uint32_t xfer_len; /* Software only - transfer len that was queued */ +}; + +/* DTD nextdesc field */ + +#define DTD_NEXTDESC_INVALID (1 << 0) /* Bit 0 : Next Descriptor Invalid. The "Terminate" bit. */ + +/* DTD config field */ + +#define DTD_CONFIG_LENGTH(n) ((n) << 16) /* Bits 16-31 : Total bytes to transfer */ +#define DTD_CONFIG_IOC (1 << 15) /* Bit 15 : Interrupt on Completion */ +#define DTD_CONFIG_MULT_VARIABLE (0 << 10) /* Bits 10-11 : Number of packets executed per transacation descriptor (override) */ +#define DTD_CONFIG_MULT_NUM(n) ((n) << 10) +#define DTD_CONFIG_ACTIVE (1 << 7) /* Bit 7 : Status Active */ +#define DTD_CONFIG_HALTED (1 << 6) /* Bit 6 : Status Halted */ +#define DTD_CONFIG_BUFFER_ERROR (1 << 5) /* Bit 6 : Status Buffer Error */ +#define DTD_CONFIG_TRANSACTION_ERROR (1 << 3) /* Bit 3 : Status Transaction Error */ + +/* This represents a queue head - note these must be aligned to a 2048 byte + * boundary + */ + +struct imx9_dqh_s +{ + uint32_t capability; /* Endpoint capability */ + uint32_t currdesc; /* Current dTD pointer */ + struct imx9_dtd_s overlay; /* DTD overlay */ + volatile uint32_t setup[2]; /* Set-up buffer */ + uint32_t gap[4]; /* align to 64 bytes */ +}; + +/* DQH capability field */ + +#define DQH_CAPABILITY_MULT_VARIABLE (0 << 30) /* Bits 30-31 : Number of packets executed per transaction descriptor */ +#define DQH_CAPABILITY_MULT_NUM(n) ((n) << 30) +#define DQH_CAPABILITY_ZLT (1 << 29) /* Bit 29 : Zero Length Termination Select */ +#define DQH_CAPABILITY_MAX_PACKET(n) ((n) << 16) /* Bits 16-29 : Maximum packet size of associated endpoint (<1024) */ +#define DQH_CAPABILITY_IOS (1 << 15) /* Bit 15 : Interrupt on Setup */ + +/* Endpoints ****************************************************************/ + +/* Number of endpoints */ + +#define IMX9_NLOGENDPOINTS (8) /* ep0-7 */ +#define IMX9_NPHYSENDPOINTS (16) /* x2 for IN and OUT */ + +/* Odd physical endpoint numbers are IN; even are OUT */ + +#define IMX9_EPPHYIN(epphy) (((epphy) & 1) != 0) +#define IMX9_EPPHYOUT(epphy) (((epphy) & 1) == 0) + +#define IMX9_EPPHYIN2LOG(epphy) (((uint8_t)(epphy) >> 1) |USB_DIR_IN) +#define IMX9_EPPHYOUT2LOG(epphy) (((uint8_t)(epphy) >> 1) | USB_DIR_OUT) + +/* Endpoint 0 is special... */ + +#define IMX9_EP0_OUT (0) +#define IMX9_EP0_IN (1) + +/* Each endpoint has somewhat different characteristics */ + +#define IMX9_EPALLSET (0xffff) /* All endpoints */ +#define IMX9_EPOUTSET (0x5555) /* Even phy endpoint numbers are OUT EPs */ +#define IMX9_EPINSET (0xaaaa) /* Odd endpoint numbers are IN EPs */ +#define IMX9_EPCTRLSET (0x0003) /* EP0 IN/OUT are control endpoints */ +#define IMX9_EPINTRSET (0x000c) /* Interrupt endpoints */ +#define IMX9_EPBULKSET (0x0ff0) /* Bulk endpoints */ +#define IMX9_EPISOCSET (0xf000) /* Isochronous endpoints */ + +/* Maximum packet sizes for endpoints */ + +#define IMX9_EP0MAXPACKET (64) /* EP0 max packet size (1-64) */ +#define IMX9_BULKMAXPACKET (512) /* Bulk endpoint max packet (8/16/32/64/512) */ +#define IMX9_INTRMAXPACKET (1024) /* Interrupt endpoint max packet (1 to 1024) */ +#define IMX9_ISOCMAXPACKET (512) /* Acutally 1..1023 */ + +/* Endpoint bit position in SETUPSTAT, PRIME, FLUSH, STAT, COMPLETE + * registers + */ + +#define IMX9_ENDPTSHIFT(epphy) (IMX9_EPPHYIN(epphy) ? (16 + ((epphy) >> 1)) : ((epphy) >> 1)) +#define IMX9_ENDPTMASK(epphy) (1 << IMX9_ENDPTSHIFT(epphy)) +#define IMX9_ENDPTMASK_ALL 0x00ff00ff + +/* Request queue operations *************************************************/ + +#define imx9_rqempty(ep) ((ep)->head == NULL) +#define imx9_rqpeek(ep) ((ep)->head) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* A container for a request so that the request may be retained in a list */ + +struct imx9_req_s +{ + struct usbdev_req_s req; /* Standard USB request */ + struct imx9_req_s *flink; /* Supports a singly linked list */ +}; + +/* This is the internal representation of an endpoint */ + +struct imx9_ep_s +{ + /* Common endpoint fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbdev_ep_s + * to struct imx9_ep_s. + */ + + struct usbdev_ep_s ep; /* Standard endpoint structure */ + + /* IMX9XX-specific fields */ + + struct imx9_usb_s *dev; /* Reference to private driver data */ + struct imx9_req_s *head; /* Request list for this endpoint */ + struct imx9_req_s *tail; + uint8_t epphy; /* Physical EP address */ + uint8_t stalled:1; /* 1: Endpoint is stalled */ +}; + +/* Structure for ep0 short transfers */ + +struct imx9_ep0_s +{ + uint8_t buf[64] CACHE_ALIGNED_DATA; /* buffer for EP0 short transfers */ + uint16_t buf_len; /* buffer length */ + struct usb_ctrlreq_s ctrl; /* structure for EP0 short transfers */ + uint8_t state; /* state of certain EP0 operations */ +}; + +/* This structure retains the state of the USB device controller */ + +struct imx9_usb_s +{ + /* Common device fields. This must be the first thing defined in the + * structure so that it is possible to simply cast from struct usbdev_s + * to struct imx9_usb_s. + */ + + struct usbdev_s usbdev; + + /* The bound device class driver */ + + struct usbdevclass_driver_s *driver; + + const int id; /* Id of the usb controller */ + const uintptr_t base; /* Base address of the controller */ + uint8_t paddr; /* Address assigned by SETADDRESS */ + uint8_t stalled:1; /* 1: Protocol stalled */ + uint8_t selfpowered:1; /* 1: Device is self powered */ + uint8_t paddrset:1; /* 1: Peripheral addr has been set */ + uint8_t attached:1; /* 1: Host attached */ + uint8_t suspended:1; /* 1: Suspended */ + uint32_t softprio; /* Bitset of high priority interrupts */ + uint32_t epavail; /* Bitset of available endpoints */ +#ifdef CONFIG_IMX9_USB_FRAME_INTERRUPT + uint32_t sof; /* Last start-of-frame */ +#endif + + struct imx9_ep0_s ep0; /* ep0 */ + + /* The endpoint list */ + + struct imx9_ep_s eplist[IMX9_NPHYSENDPOINTS]; + + struct imx9_dqh_s qh[IMX9_NPHYSENDPOINTS] aligned_data(2048); + + struct imx9_dtd_s td[IMX9_NPHYSENDPOINTS] aligned_data(32); +}; + +#define EP0STATE_IDLE 0 /* Idle State, leave on receiving a setup packet or epsubmit */ +#define EP0STATE_SETUP_OUT 1 /* Setup Packet received - SET/CLEAR */ +#define EP0STATE_SETUP_IN 2 /* Setup Packet received - GET */ +#define EP0STATE_SHORTREAD 3 /* Short read without a usb_request */ +#define EP0STATE_SHORTWRITE 4 /* Short write without a usb_request */ +#define EP0STATE_WAIT_NAK_OUT 5 /* Waiting for Host to illicit status phase (GET) */ +#define EP0STATE_WAIT_NAK_IN 6 /* Waiting for Host to illicit status phase (SET/CLEAR) */ +#define EP0STATE_WAIT_STATUS_OUT 7 /* Wait for status phase to complete */ +#define EP0STATE_WAIT_STATUS_IN 8 /* Wait for status phase to complete */ +#define EP0STATE_DATA_IN 9 +#define EP0STATE_DATA_OUT 10 + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register operations ******************************************************/ + +#ifdef CONFIG_IMX9_USB_REGDEBUG +static uint32_t imx9_getreg(struct imx9_usb_s *priv, off_t offset); +static void imx9_putreg(struct imx9_usb_s *priv, off_t offset, uint32_t val); +#else +# define imx9_getreg(priv, offset) getreg32(priv->base + offset) +# define imx9_putreg(priv, offset, val) putreg32(val,priv->base + offset) +#endif + +static inline void imx9_modifyreg(struct imx9_usb_s *priv, + off_t offset, + uint32_t clear, + uint32_t set); + +/* Request queue operations *************************************************/ + +static struct imx9_req_s *imx9_rqdequeue( + struct imx9_ep_s *privep); +static bool imx9_rqenqueue(struct imx9_ep_s *privep, + struct imx9_req_s *req); + +/* Low level data transfers and request operations **************************/ + +static inline void imx9_writedtd(struct imx9_dtd_s *dtd, + const uint8_t *data, + uint32_t nbytes); +static inline void imx9_queuedtd(struct imx9_usb_s *priv, uint8_t epphy, + struct imx9_dtd_s *dtd); +static inline void imx9_ep0xfer(struct imx9_usb_s *priv, uint8_t epphy, + uint8_t *data, + uint32_t nbytes); +static void imx9_readsetup(struct imx9_usb_s *priv, uint8_t epphy, + struct usb_ctrlreq_s *ctrl); +static inline void imx9_set_address(struct imx9_usb_s *priv, + uint16_t address); + +static void imx9_flushep(struct imx9_ep_s *privep); + +static int imx9_progressep(struct imx9_ep_s *privep); +static void imx9_reqcomplete(struct imx9_ep_s *privep, + struct imx9_req_s *privreq, int16_t result); + +static void imx9_cancelrequests(struct imx9_ep_s *privep, + int16_t status); + +/* Interrupt handling *******************************************************/ + +static struct imx9_ep_s *imx9_epfindbyaddr(struct imx9_usb_s *priv, + uint16_t eplog); +static void imx9_dispatchrequest(struct imx9_usb_s *priv, + const struct usb_ctrlreq_s *ctrl); +static void imx9_ep0configure(struct imx9_usb_s *priv); +static void imx9_usbreset(struct imx9_usb_s *priv); +static inline void imx9_ep0state(struct imx9_usb_s *priv, + uint16_t state); +static void imx9_ep0setup(struct imx9_usb_s *priv); +static void imx9_ep0complete(struct imx9_usb_s *priv, + uint8_t epphy); +static void imx9_ep0nak(struct imx9_usb_s *priv, uint8_t epphy); +static bool imx9_epcomplete(struct imx9_usb_s *priv, + uint8_t epphy); +static int imx9_usbinterrupt(int irq, void *context, + void *arg); + +/* Endpoint operations ******************************************************/ + +/* USB device controller operations *****************************************/ + +static int imx9_epconfigure(struct usbdev_ep_s *ep, + const struct usb_epdesc_s *desc, bool last); +static int imx9_epdisable(struct usbdev_ep_s *ep); +static struct usbdev_req_s *imx9_epallocreq(struct usbdev_ep_s *ep); +static void imx9_epfreereq(struct usbdev_ep_s *ep, + struct usbdev_req_s *); +#ifdef CONFIG_USBDEV_DMA +static void *imx9_epallocbuffer(struct usbdev_ep_s *ep, + uint16_t bytes); +static void imx9_epfreebuffer(struct usbdev_ep_s *ep, + void *buf); +#endif +static int imx9_epsubmit(struct usbdev_ep_s *ep, + struct usbdev_req_s *req); +static int imx9_epcancel(struct usbdev_ep_s *ep, + struct usbdev_req_s *req); +static int imx9_epstall(struct usbdev_ep_s *ep, bool resume); + +static struct usbdev_ep_s *imx9_allocep(struct usbdev_s *dev, + uint8_t epno, bool in, uint8_t eptype); +static void imx9_freeep(struct usbdev_s *dev, + struct usbdev_ep_s *ep); +static int imx9_getframe(struct usbdev_s *dev); +static int imx9_wakeup(struct usbdev_s *dev); +static int imx9_selfpowered(struct usbdev_s *dev, bool selfpowered); +static int imx9_pullup(struct usbdev_s *dev, bool enable); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct imx9_usb_s g_usbdev[] = +{ +#ifdef CONFIG_IMX9_USBDEV_USBC1 + { + .id = 0, + .base = IMX9_USB_OTG1_BASE, + }, +#endif + +#ifdef CONFIG_IMX9_USBDEV_USBC2 + { + .id = 1, + .base = IMX9_USB_OTG2_BASE, + }, +#endif +}; + +static const int n_usbdevs = sizeof(g_usbdev) / sizeof(g_usbdev[0]); + +static const struct usbdev_epops_s g_epops = +{ + .configure = imx9_epconfigure, + .disable = imx9_epdisable, + .allocreq = imx9_epallocreq, + .freereq = imx9_epfreereq, +#ifdef CONFIG_USBDEV_DMA + .allocbuffer = imx9_epallocbuffer, + .freebuffer = imx9_epfreebuffer, +#endif + .submit = imx9_epsubmit, + .cancel = imx9_epcancel, + .stall = imx9_epstall, +}; + +static const struct usbdev_ops_s g_devops = +{ + .allocep = imx9_allocep, + .freeep = imx9_freeep, + .getframe = imx9_getframe, + .wakeup = imx9_wakeup, + .selfpowered = imx9_selfpowered, + .pullup = imx9_pullup, +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_getreg + * + * Description: + * Get the contents of an IMX93x register + * + ****************************************************************************/ + +#ifdef CONFIG_IMX9_USB_REGDEBUG +static uint32_t imx9_getreg(struct imx9_usb_s *priv, off_t offset) +{ + static uint32_t prevaddr = 0; + static uint32_t preval = 0; + static uint32_t count = 0; + + /* Read the value from the register */ + + uint32_t val = getreg32(priv->base + offset); + + /* Is this the same value that we read from the same register last time? + * Are we polling the register? If so, suppress some of the output. + */ + + if (addr == prevaddr && val == preval) + { + if (count == 0xffffffff || ++count > 3) + { + if (count == 4) + { + uinfo("...\n"); + } + + return val; + } + } + + /* No this is a new address or value */ + + else + { + /* Did we print "..." for the previous value? */ + + if (count > 3) + { + /* Yes.. then show how many times the value repeated */ + + uinfo("[repeats %d more times]\n", count - 3); + } + + /* Save the new address, value, and count */ + + prevaddr = addr; + preval = val; + count = 1; + } + + /* Show the register value read */ + + uinfo("%08x->%08x\n", priv->base + offset, val); + return val; +} +#endif + +/**************************************************************************** + * Name: imx9_putreg + * + * Description: + * Set the contents of an IMX93x register to a value + * + ****************************************************************************/ + +#ifdef CONFIG_IMX9_USB_REGDEBUG +static void imx9_putreg(struct imx9_usb_s *priv, off_t offset, uint32_t val) +{ + /* Show the register value being written */ + + uinfo("%08x<-%08x\n", priv->base + offset, val); + + /* Write the value */ + + putreg32(val, priv->base + offset); +} +#endif + +/**************************************************************************** + * Name: imx9_modifyreg + * + * Description: + * Change bits in a register + * + ****************************************************************************/ + +static inline void imx9_modifyreg(struct imx9_usb_s *priv, off_t offset, + uint32_t clear, uint32_t set) +{ + uint32_t reg = imx9_getreg(priv, offset); + reg &= ~clear; + reg |= set; + imx9_putreg(priv, offset, reg); +} + +/**************************************************************************** + * Name: imx9_rqdequeue + * + * Description: + * Remove a request from an endpoint request queue + * + ****************************************************************************/ + +static struct imx9_req_s *imx9_rqdequeue(struct imx9_ep_s *privep) +{ + struct imx9_req_s *ret = privep->head; + + if (ret) + { + privep->head = ret->flink; + if (!privep->head) + { + privep->tail = NULL; + } + + ret->flink = NULL; + } + + return ret; +} + +/**************************************************************************** + * Name: imx9_rqenqueue + * + * Description: + * Add a request from an endpoint request queue + * + ****************************************************************************/ + +static bool imx9_rqenqueue(struct imx9_ep_s *privep, + struct imx9_req_s *req) +{ + bool is_empty = !privep->head; + + req->flink = NULL; + if (is_empty) + { + privep->head = req; + privep->tail = req; + } + else + { + privep->tail->flink = req; + privep->tail = req; + } + + return is_empty; +} + +/**************************************************************************** + * Name: imx9_writedtd + * + * Description: + * Initialise a DTD to transfer the data + * + ****************************************************************************/ + +static inline void imx9_writedtd(struct imx9_dtd_s *dtd, + const uint8_t *data, + uint32_t nbytes) +{ + dtd->nextdesc = DTD_NEXTDESC_INVALID; + dtd->config = DTD_CONFIG_LENGTH(nbytes) | DTD_CONFIG_IOC | + DTD_CONFIG_ACTIVE; + dtd->buffer0 = (uint32_t)((uintptr_t) data); + dtd->buffer1 = (uint32_t)(((uintptr_t) data) + 0x1000) & 0xfffff000; + dtd->buffer2 = (uint32_t)(((uintptr_t) data) + 0x2000) & 0xfffff000; + dtd->buffer3 = (uint32_t)(((uintptr_t) data) + 0x3000) & 0xfffff000; + dtd->buffer4 = (uint32_t)(((uintptr_t) data) + 0x4000) & 0xfffff000; + dtd->xfer_len = nbytes; + + up_flush_dcache((uintptr_t)dtd, + (uintptr_t)dtd + sizeof(struct imx9_dtd_s)); + up_flush_dcache((uintptr_t)data, + (uintptr_t)data + nbytes); +} + +/**************************************************************************** + * Name: imx9_queuedtd + * + * Description: + * Add the DTD to the device list + * + * Assumptions: + * DTD is already flushed to RAM. + * + ****************************************************************************/ + +static void imx9_queuedtd(struct imx9_usb_s *priv, uint8_t epphy, + struct imx9_dtd_s *dtd) +{ + struct imx9_dqh_s *dqh = &priv->qh[epphy]; + + /* Queue the DTD onto the Endpoint + * NOTE - this only works when no DTD is currently queued + */ + + dqh->overlay.nextdesc = (uint32_t)(uintptr_t)dtd; + dqh->overlay.config &= ~(DTD_CONFIG_ACTIVE | DTD_CONFIG_HALTED); + + up_flush_dcache((uintptr_t)dqh, + (uintptr_t)dqh + sizeof(struct imx9_dqh_s)); + + uint32_t bit = IMX9_ENDPTMASK(epphy); + + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTPRIME_OFFSET, 0, bit); + + while (imx9_getreg(priv, IMX9_USBDEV_ENDPTPRIME_OFFSET) & bit); +} + +/**************************************************************************** + * Name: imx9_ep0xfer + * + * Description: + * Schedule a short transfer for Endpoint 0 (IN or OUT) + * + ****************************************************************************/ + +static inline void imx9_ep0xfer(struct imx9_usb_s *priv, uint8_t epphy, + uint8_t *buf, uint32_t nbytes) +{ + struct imx9_dtd_s *dtd = &priv->td[epphy]; + + imx9_writedtd(dtd, buf, nbytes); + + imx9_queuedtd(priv, epphy, dtd); +} + +/**************************************************************************** + * Name: imx9_readsetup + * + * Description: + * Read a Setup packet from the DTD. + * + ****************************************************************************/ + +static void imx9_readsetup(struct imx9_usb_s *priv, uint8_t epphy, + struct usb_ctrlreq_s *ctrl) +{ + struct imx9_dqh_s *dqh = &priv->qh[epphy]; + int i; + + do + { + /* Set the trip wire */ + + imx9_modifyreg(priv, IMX9_USBDEV_USBCMD_OFFSET, 0, USBDEV_USBCMD_SUTW); + + up_invalidate_dcache((uintptr_t)dqh, + (uintptr_t)dqh + sizeof(struct imx9_dqh_s)); + + /* Copy the request... */ + + for (i = 0; i < 8; i++) + { + ((uint8_t *) ctrl)[i] = ((uint8_t *) dqh->setup)[i]; + } + } + + while (!(imx9_getreg(priv, + IMX9_USBDEV_USBCMD_OFFSET) & USBDEV_USBCMD_SUTW)); + + /* Clear the trip wire */ + + imx9_modifyreg(priv, IMX9_USBDEV_USBCMD_OFFSET, USBDEV_USBCMD_SUTW, 0); + + /* Clear the Setup Interrupt */ + + imx9_putreg(priv, IMX9_USBDEV_ENDPTSETUPSTAT_OFFSET, + IMX9_ENDPTMASK(IMX9_EP0_OUT)); +} + +/**************************************************************************** + * Name: imx9_set_address + * + * Description: + * Set the devices USB address + * + ****************************************************************************/ + +static inline void imx9_set_address(struct imx9_usb_s *priv, + uint16_t address) +{ + priv->paddr = address; + priv->paddrset = address != 0; + + imx9_modifyreg(priv, IMX9_USBDEV_DEVICEADDR_OFFSET, USBDEV_DEVICEADDR_MASK, + priv->paddr << USBDEV_DEVICEADDR_SHIFT); +} + +/**************************************************************************** + * Name: imx9_flushep + * + * Description: + * Flush any primed descriptors from this ep + * + ****************************************************************************/ + +static void imx9_flushep(struct imx9_ep_s *privep) +{ + uint32_t mask = IMX9_ENDPTMASK(privep->epphy); + struct imx9_usb_s *priv = privep->dev; + + do + { + imx9_putreg(priv, IMX9_USBDEV_ENDPTFLUSH_OFFSET, mask); + while ((imx9_getreg(priv, IMX9_USBDEV_ENDPTFLUSH_OFFSET) & mask) != 0); + } + while ((imx9_getreg(priv, IMX9_USBDEV_ENDPTSTATUS_OFFSET) & mask) != 0); +} + +/**************************************************************************** + * Name: imx9_progressep + * + * Description: + * Progress the Endpoint by priming the first request into the queue head + * + ****************************************************************************/ + +static int imx9_progressep(struct imx9_ep_s *privep) +{ + struct imx9_usb_s *priv = privep->dev; + struct imx9_dtd_s *dtd = &priv->td[privep->epphy]; + struct imx9_req_s *privreq; + + /* Check the request from the head of the endpoint request queue */ + + privreq = imx9_rqpeek(privep); + if (!privreq) + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EPINQEMPTY), 0); + return OK; + } + + /* Ignore any attempt to send a zero length packet */ + + if (privreq->req.len == 0) + { + /* If the class driver is responding to a setup packet, then wait for + * the host to illicit the response + */ + + if (privep->epphy == IMX9_EP0_IN && + privep->dev->ep0.state == EP0STATE_SETUP_OUT) + { + imx9_ep0state(priv, EP0STATE_WAIT_NAK_IN); + } + else + { + if (IMX9_EPPHYIN(privep->epphy)) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_EPINNULLPACKET), 0); + } + else + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_EPOUTNULLPACKET), 0); + } + } + + imx9_reqcomplete(privep, imx9_rqdequeue(privep), OK); + return OK; + } + + if (privep->epphy == IMX9_EP0_IN) + { + imx9_ep0state(priv, EP0STATE_DATA_IN); + } + else if (privep->epphy == IMX9_EP0_OUT) + { + imx9_ep0state(priv, EP0STATE_DATA_OUT); + } + + int bytesleft = privreq->req.len - privreq->req.xfrd; + + if (IMX9_EPPHYIN(privep->epphy)) + { + usbtrace(TRACE_WRITE(privep->epphy), privreq->req.xfrd); + } + else + { + usbtrace(TRACE_READ(privep->epphy), privreq->req.xfrd); + } + + /* Initialise the DTD to transfer the next chunk */ + + imx9_writedtd(dtd, privreq->req.buf + privreq->req.xfrd, bytesleft); + + /* Then queue onto the DQH */ + + imx9_queuedtd(priv, privep->epphy, dtd); + + return OK; +} + +/**************************************************************************** + * Name: imx9_reqcomplete + * + * Description: + * Handle termination of the request at the head of the endpoint request + * queue. + * + ****************************************************************************/ + +static void imx9_reqcomplete(struct imx9_ep_s *privep, + struct imx9_req_s *privreq, int16_t result) +{ + /* If endpoint 0, temporarily reflect the state of protocol stalled + * in the callback. + */ + + bool stalled = privep->stalled; + if (privep->epphy == IMX9_EP0_IN) + privep->stalled = privep->dev->stalled; + + /* Save the result in the request structure */ + + privreq->req.result = result; + + /* Callback to the request completion handler */ + + privreq->req.callback(&privep->ep, &privreq->req); + + /* Restore the stalled indication */ + + privep->stalled = stalled; +} + +/**************************************************************************** + * Name: imx9_cancelrequests + * + * Description: + * Cancel all pending requests for an endpoint + * + ****************************************************************************/ + +static void imx9_cancelrequests(struct imx9_ep_s *privep, int16_t status) +{ + if (!imx9_rqempty(privep)) + imx9_flushep(privep); + + while (!imx9_rqempty(privep)) + { + /* FIXME: the entry at the head should be sync'd with the DTD + * FIXME: only report the error status if the transfer hasn't completed + */ + + usbtrace(TRACE_COMPLETE(privep->epphy), + (imx9_rqpeek(privep))->req.xfrd); + imx9_reqcomplete(privep, imx9_rqdequeue(privep), status); + } +} + +/**************************************************************************** + * Name: imx9_epfindbyaddr + * + * Description: + * Find the physical endpoint structure corresponding to a logic endpoint + * address + * + ****************************************************************************/ + +static struct imx9_ep_s *imx9_epfindbyaddr(struct imx9_usb_s *priv, + uint16_t eplog) +{ + struct imx9_ep_s *privep; + int i; + + /* Endpoint zero is a special case */ + + if (USB_EPNO(eplog) == 0) + { + return &priv->eplist[0]; + } + + /* Handle the remaining */ + + for (i = 1; i < IMX9_NPHYSENDPOINTS; i++) + { + privep = &priv->eplist[i]; + + /* Same logical endpoint number? (includes direction bit) */ + + if (eplog == privep->ep.eplog) + { + /* Return endpoint found */ + + return privep; + } + } + + /* Return endpoint not found */ + + return NULL; +} + +/**************************************************************************** + * Name: imx9_dispatchrequest + * + * Description: + * Provide unhandled setup actions to the class driver. This is logically + * part of the USB interrupt handler. + * + ****************************************************************************/ + +static void imx9_dispatchrequest(struct imx9_usb_s *priv, + const struct usb_ctrlreq_s *ctrl) +{ + int ret = -EIO; + + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_DISPATCH), 0); + if (priv->driver) + { + /* Forward to the control request to the class driver implementation */ + + ret = CLASS_SETUP(priv->driver, &priv->usbdev, ctrl, priv->ep0.buf, + priv->ep0.buf_len); + } + + if (ret < 0) + { + /* Stall on failure */ + + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_DISPATCHSTALL), 0); + priv->stalled = true; + } +} + +/**************************************************************************** + * Name: imx9_ep0configure + * + * Description: + * Reset Usb engine + * + ****************************************************************************/ + +static void imx9_ep0configure(struct imx9_usb_s *priv) +{ + /* Enable ep0 IN and ep0 OUT */ + + priv->qh[IMX9_EP0_OUT].capability = + (DQH_CAPABILITY_MAX_PACKET(CONFIG_USBDEV_EP0_MAXSIZE) | + DQH_CAPABILITY_IOS | DQH_CAPABILITY_ZLT); + + priv->qh[IMX9_EP0_IN].capability = + (DQH_CAPABILITY_MAX_PACKET(CONFIG_USBDEV_EP0_MAXSIZE) | + DQH_CAPABILITY_IOS | DQH_CAPABILITY_ZLT); + + priv->qh[IMX9_EP0_OUT].currdesc = DTD_NEXTDESC_INVALID; + priv->qh[IMX9_EP0_IN].currdesc = DTD_NEXTDESC_INVALID; + + up_clean_dcache((uintptr_t)priv->qh, + (uintptr_t)priv->qh + (sizeof(struct imx9_dqh_s) * 2)); + + /* Enable EP0 */ + + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL0_OFFSET, 0, + USBDEV_ENDPTCTRL0_RXE | USBDEV_ENDPTCTRL0_TXE); +} + +/**************************************************************************** + * Name: imx9_usbreset + * + * Description: + * Reset Usb engine + * + ****************************************************************************/ + +static void imx9_usbreset(struct imx9_usb_s *priv) +{ + int epphy; + + /* Disable all endpoints. Control endpoint 0 is always enabled */ + + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL1_OFFSET, + USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, 0); + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL2_OFFSET, + USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, 0); + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL3_OFFSET, + USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, 0); + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL4_OFFSET, + USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, 0); + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL5_OFFSET, + USBDEV_ENDPTCTRL_RXE | USBDEV_ENDPTCTRL_TXE, 0); + + /* Clear all pending interrupts */ + + imx9_putreg(priv, IMX9_USBDEV_ENDPTNAK_OFFSET, + imx9_getreg(priv, IMX9_USBDEV_ENDPTNAK_OFFSET)); + + imx9_putreg(priv, IMX9_USBDEV_ENDPTSETUPSTAT_OFFSET, + imx9_getreg(priv, IMX9_USBDEV_ENDPTSETUPSTAT_OFFSET)); + + imx9_putreg(priv, IMX9_USBDEV_ENDPTCOMPLETE_OFFSET, + imx9_getreg(priv, IMX9_USBDEV_ENDPTCOMPLETE_OFFSET)); + + /* Wait for all prime operations to have completed and then flush all + * DTDs + */ + + while (imx9_getreg(priv, IMX9_USBDEV_ENDPTPRIME_OFFSET) != 0); + + imx9_putreg(priv, IMX9_USBDEV_ENDPTFLUSH_OFFSET, IMX9_ENDPTMASK_ALL); + + while (imx9_getreg(priv, IMX9_USBDEV_ENDPTFLUSH_OFFSET)); + + /* Reset endpoints */ + + for (epphy = 0; epphy < IMX9_NPHYSENDPOINTS; epphy++) + { + struct imx9_ep_s *privep = &priv->eplist[epphy]; + + imx9_cancelrequests(privep, -ESHUTDOWN); + + /* Reset endpoint status */ + + privep->stalled = false; + } + + /* Tell the class driver that we are disconnected. The class + * driver should then accept any new configurations. + */ + + if (priv->driver) + { + CLASS_DISCONNECT(priv->driver, &priv->usbdev); + } + + /* Set the interrupt Threshold control interval to 0 */ + + imx9_modifyreg(priv, IMX9_USBDEV_USBCMD_OFFSET, USBDEV_USBCMD_ITC_MASK, + USBDEV_USBCMD_ITCIMME); + + /* Zero out the Endpoint queue heads */ + + memset ((void *)priv->qh, 0, sizeof(priv->qh)); + memset ((void *)priv->td, 0, sizeof(priv->td)); + + up_clean_dcache((uintptr_t)priv->qh, + (uintptr_t)priv->qh + sizeof(priv->qh)); + up_clean_dcache((uintptr_t)priv->td, + (uintptr_t)priv->td + sizeof(priv->td)); + + /* Set USB address to 0 */ + + imx9_set_address(priv, 0); + + /* Initialise the Enpoint List Address */ + + imx9_putreg(priv, IMX9_USBDEV_ENDPOINTLIST_OFFSET, + (uint32_t)(uintptr_t)priv->qh); + + /* EndPoint 0 initialization */ + + imx9_ep0configure(priv); + + /* Enable Device interrupts */ + + imx9_putreg(priv, IMX9_USBDEV_USBINTR_OFFSET, + USB_FRAME_INT | USB_ERROR_INT | USBDEV_USBINTR_NAKE | + USBDEV_USBINTR_SLE | USBDEV_USBINTR_URE | USBDEV_USBINTR_PCE | + USBDEV_USBINTR_UE); +} + +/**************************************************************************** + * Name: imx9_setstate + * + * Description: + * Sets the EP0 state and manages the NAK interrupts + * + ****************************************************************************/ + +static inline void imx9_ep0state(struct imx9_usb_s *priv, + uint16_t state) +{ + priv->ep0.state = state; + + switch (state) + { + case EP0STATE_WAIT_NAK_IN: + imx9_putreg(priv, IMX9_USBDEV_ENDPTNAKEN_OFFSET, + IMX9_ENDPTMASK(IMX9_EP0_IN)); + break; + + case EP0STATE_WAIT_NAK_OUT: + imx9_putreg(priv, IMX9_USBDEV_ENDPTNAKEN_OFFSET, + IMX9_ENDPTMASK(IMX9_EP0_OUT)); + break; + + default: + imx9_putreg(priv, IMX9_USBDEV_ENDPTNAKEN_OFFSET, 0); + break; + } +} + +/**************************************************************************** + * Name: imx9_ep0setup + * + * Description: + * USB Ctrl EP Setup Event. This is logically part of the USB interrupt + * handler. This event occurs when a setup packet is receive on EP0 OUT. + * + ****************************************************************************/ + +static inline void imx9_ep0setup(struct imx9_usb_s *priv) +{ + struct imx9_ep_s *privep; + struct usb_ctrlreq_s *ctrl; + uint16_t value; + uint16_t index; + uint16_t len; + + ctrl = &priv->ep0.ctrl; + + /* Terminate any pending requests - since all DTDs will have been retired + * because of the setup packet. + */ + + imx9_cancelrequests(&priv->eplist[IMX9_EP0_OUT], -EPROTO); + imx9_cancelrequests(&priv->eplist[IMX9_EP0_IN], -EPROTO); + + /* Assume NOT stalled */ + + priv->eplist[IMX9_EP0_OUT].stalled = false; + priv->eplist[IMX9_EP0_IN].stalled = false; + priv->stalled = false; + + /* Read EP0 setup data */ + + imx9_readsetup(priv, IMX9_EP0_OUT, ctrl); + + /* And extract the little-endian 16-bit values to host order */ + + value = GETUINT16(ctrl->value); + index = GETUINT16(ctrl->index); + len = GETUINT16(ctrl->len); + + priv->ep0.buf_len = len; + + uinfo("type=%02x req=%02x value=%04x index=%04x len=%04x\n", + ctrl->type, ctrl->req, value, index, len); + + /* Starting a control request - update state */ + + if (ctrl->type & USB_REQ_DIR_IN) + { + imx9_ep0state(priv, EP0STATE_SETUP_IN); + } + else + { + imx9_ep0state(priv, EP0STATE_SETUP_OUT); + + if (len > 0) + { + imx9_ep0state(priv, EP0STATE_SHORTREAD); + imx9_ep0xfer(priv, IMX9_EP0_OUT, priv->ep0.buf, len); + return; + } + } + + /* Dispatch any non-standard requests */ + + if ((ctrl->type & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) + { + imx9_dispatchrequest(priv, ctrl); + } + else + { + /* Handle standard request. Pick off the things of interest to the USB + * device controller driver; pass what is left to the class driver. + */ + + switch (ctrl->req) + { + case USB_REQ_GETSTATUS: + { + /* type: device-to-host; recipient = device, interface, endpoint + * value: 0 + * index: zero interface endpoint + * len: 2; data = status + */ + + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_GETSTATUS), 0); + if (!priv->paddrset || len != 2 || + (ctrl->type & USB_REQ_DIR_IN) == 0 || value != 0) + { + priv->stalled = true; + } + else + { + switch (ctrl->type & USB_REQ_RECIPIENT_MASK) + { + case USB_REQ_RECIPIENT_ENDPOINT: + { + usbtrace( + TRACE_INTDECODE(IMX9_TRACEINTID_EPGETSTATUS), 0); + privep = imx9_epfindbyaddr(priv, index); + if (!privep) + { + usbtrace( + TRACE_DEVERROR(IMX9_TRACEERR_BADEPGETSTATUS), + 0); + priv->stalled = true; + } + else + { + if (privep->stalled) + { + priv->ep0.buf[0] = 1; /* Stalled */ + } + else + { + priv->ep0.buf[0] = 0; /* Not stalled */ + } + + priv->ep0.buf[1] = 0; + + imx9_ep0xfer(priv, IMX9_EP0_IN, priv->ep0.buf, 2); + imx9_ep0state(priv, EP0STATE_SHORTWRITE); + } + } + break; + + case USB_REQ_RECIPIENT_DEVICE: + { + if (index == 0) + { + usbtrace( + TRACE_INTDECODE(IMX9_TRACEINTID_DEVGETSTATUS), + 0); + + /* Features: Remote Wakeup=YES; selfpowered=? */ + + priv->ep0.buf[0] = + (priv->selfpowered << USB_FEATURE_SELFPOWERED) | + (1 << USB_FEATURE_REMOTEWAKEUP); + priv->ep0.buf[1] = 0; + + imx9_ep0xfer(priv, IMX9_EP0_IN, priv->ep0.buf, 2); + imx9_ep0state(priv, EP0STATE_SHORTWRITE); + } + else + { + usbtrace( + TRACE_DEVERROR(IMX9_TRACEERR_BADDEVGETSTATUS), + 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_RECIPIENT_INTERFACE: + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_IFGETSTATUS), + 0); + priv->ep0.buf[0] = 0; + priv->ep0.buf[1] = 0; + + imx9_ep0xfer(priv, IMX9_EP0_IN, priv->ep0.buf, 2); + imx9_ep0state(priv, EP0STATE_SHORTWRITE); + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADGETSTATUS), + 0); + priv->stalled = true; + } + break; + } + } + } + break; + + case USB_REQ_CLEARFEATURE: + { + /* type: host-to-device; recipient = device, interface or endpoint + * value: feature selector + * index: zero interface endpoint; + * len: zero, data = none + */ + + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_CLEARFEATURE), 0); + if ((ctrl->type & USB_REQ_RECIPIENT_MASK) != + USB_REQ_RECIPIENT_ENDPOINT) + { + imx9_dispatchrequest(priv, ctrl); + } + else if (priv->paddrset != 0 && + value == USB_FEATURE_ENDPOINTHALT && + len == 0 && (privep = imx9_epfindbyaddr(priv, index)) != NULL) + { + imx9_epstall(&privep->ep, true); + imx9_ep0state(priv, EP0STATE_WAIT_NAK_IN); + } + else + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADCLEARFEATURE), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_SETFEATURE: + { + /* type: host-to-device; recipient = device, interface, endpoint + * value: feature selector + * index: zero interface endpoint; + * len: 0; data = none + */ + + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_SETFEATURE), 0); + if (((ctrl->type & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_DEVICE) && value == USB_FEATURE_TESTMODE) + { + uinfo("test mode: %d\n", index); + } + else if ((ctrl->type & USB_REQ_RECIPIENT_MASK) != + USB_REQ_RECIPIENT_ENDPOINT) + { + imx9_dispatchrequest(priv, ctrl); + } + else if (priv->paddrset != 0 && + value == USB_FEATURE_ENDPOINTHALT && + len == 0 && (privep = imx9_epfindbyaddr(priv, index)) != NULL) + { + imx9_epstall(&privep->ep, false); + imx9_ep0state(priv, EP0STATE_WAIT_NAK_IN); + } + else + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADSETFEATURE), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_SETADDRESS: + { + /* type: host-to-device; recipient = device + * value: device address + * index: 0 + * len: 0; data = none + */ + + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EP0SETUPSETADDRESS), + value); + if (((ctrl->type & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_DEVICE) && + index == 0 && len == 0 && value < 128) + { + /* Save the address. We cannot actually change to the next + * address until the completion of the status phase. + */ + + priv->paddr = ctrl->value[0]; + priv->paddrset = false; + imx9_ep0state(priv, EP0STATE_WAIT_NAK_IN); + } + else + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADSETADDRESS), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_GETDESCRIPTOR: + /* type: device-to-host; recipient = device + * value: descriptor type and index + * index: 0 or language ID; + * len: descriptor len; data = descriptor + */ + + case USB_REQ_SETDESCRIPTOR: + /* type: host-to-device; recipient = device + * value: descriptor type and index + * index: 0 or language ID; + * len: descriptor len; data = descriptor + */ + + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_GETSETDESC), 0); + if ((ctrl->type & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_DEVICE) + { + imx9_dispatchrequest(priv, ctrl); + } + else + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADGETSETDESC), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_GETCONFIGURATION: + /* type: device-to-host; recipient = device + * value: 0; + * index: 0; + * len: 1; data = configuration value + */ + + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_GETCONFIG), 0); + if (priv->paddrset && + ((ctrl->type & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_DEVICE) && + value == 0 && index == 0 && len == 1) + { + imx9_dispatchrequest(priv, ctrl); + } + else + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADGETCONFIG), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_SETCONFIGURATION: + /* type: host-to-device; recipient = device + * value: configuration value + * index: 0; + * len: 0; data = none + */ + + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_SETCONFIG), 0); + if (((ctrl->type & USB_REQ_RECIPIENT_MASK) == + USB_REQ_RECIPIENT_DEVICE) && index == 0 && len == 0) + { + imx9_dispatchrequest(priv, ctrl); + } + else + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADSETCONFIG), 0); + priv->stalled = true; + } + } + break; + + case USB_REQ_GETINTERFACE: + /* type: device-to-host; recipient = interface + * value: 0 + * index: interface; + * len: 1; data = alt interface + */ + + case USB_REQ_SETINTERFACE: + /* type: host-to-device; recipient = interface + * value: alternate setting + * index: interface; + * len: 0; data = none + */ + + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_GETSETIF), 0); + imx9_dispatchrequest(priv, ctrl); + } + break; + + case USB_REQ_SYNCHFRAME: + /* type: device-to-host; recipient = endpoint + * value: 0 + * index: endpoint; + * len: 2; data = frame number + */ + + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_SYNCHFRAME), 0); + } + break; + + default: + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_INVALIDCTRLREQ), 0); + priv->stalled = true; + } + break; + } + } + + if (priv->stalled) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_EP0SETUPSTALLED), + priv->ep0.state); + imx9_epstall(&priv->eplist[IMX9_EP0_IN].ep, false); + imx9_epstall(&priv->eplist[IMX9_EP0_OUT].ep, false); + } +} + +/**************************************************************************** + * Name: imx9_ep0complete + * + * Description: + * Transfer complete handler for Endpoint 0 + * + ****************************************************************************/ + +static void imx9_ep0complete(struct imx9_usb_s *priv, uint8_t epphy) +{ + struct imx9_ep_s *privep = &priv->eplist[epphy]; + + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EP0COMPLETE), + (uint16_t)priv->ep0.state); + + switch (priv->ep0.state) + { + case EP0STATE_DATA_IN: + if (imx9_rqempty(privep)) + { + return; + } + + if (imx9_epcomplete(priv, epphy)) + { + imx9_ep0state(priv, EP0STATE_WAIT_NAK_OUT); + } + break; + + case EP0STATE_DATA_OUT: + if (imx9_rqempty(privep)) + { + return; + } + + if (imx9_epcomplete(priv, epphy)) + { + imx9_ep0state(priv, EP0STATE_WAIT_NAK_IN); + } + break; + + case EP0STATE_SHORTREAD: + + /* Make sure we have updated data after the DMA transfer. + * This invalidation matches the flush in writedtd(). + */ + + up_invalidate_dcache((uintptr_t)priv->ep0.buf, + (uintptr_t)priv->ep0.buf + sizeof(priv->ep0.buf)); + + imx9_dispatchrequest(priv, &priv->ep0.ctrl); + imx9_ep0state(priv, EP0STATE_WAIT_NAK_IN); + break; + + case EP0STATE_SHORTWRITE: + imx9_ep0state(priv, EP0STATE_WAIT_NAK_OUT); + break; + + case EP0STATE_WAIT_STATUS_IN: + imx9_ep0state(priv, EP0STATE_IDLE); + + /* If we've received a SETADDRESS packet, then we set the address + * now that the status phase has completed + */ + + if (!priv->paddrset && priv->paddr != 0) + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EP0INSETADDRESS), + (uint16_t)priv->paddr); + imx9_set_address(priv, priv->paddr); + } + + break; + + case EP0STATE_WAIT_STATUS_OUT: + imx9_ep0state(priv, EP0STATE_IDLE); + break; + + default: +#ifdef CONFIG_DEBUG_FEATURES + DEBUGASSERT(priv->ep0.state != EP0STATE_DATA_IN && + priv->ep0.state != EP0STATE_DATA_OUT && + priv->ep0.state != EP0STATE_SHORTWRITE && + priv->ep0.state != EP0STATE_WAIT_STATUS_IN && + priv->ep0.state != EP0STATE_WAIT_STATUS_OUT); +#endif + priv->stalled = true; + break; + } + + if (priv->stalled) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_EP0SETUPSTALLED), + priv->ep0.state); + imx9_epstall(&priv->eplist[IMX9_EP0_IN].ep, false); + imx9_epstall(&priv->eplist[IMX9_EP0_OUT].ep, false); + } +} + +/**************************************************************************** + * Name: imx9_ep0nak + * + * Description: + * Handle a NAK interrupt on EP0 + * + ****************************************************************************/ + +static void imx9_ep0nak(struct imx9_usb_s *priv, uint8_t epphy) +{ + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EP0NAK), + (uint16_t)priv->ep0.state); + + switch (priv->ep0.state) + { + case EP0STATE_WAIT_NAK_IN: + imx9_ep0xfer(priv, IMX9_EP0_IN, NULL, 0); + imx9_ep0state(priv, EP0STATE_WAIT_STATUS_IN); + break; + + case EP0STATE_WAIT_NAK_OUT: + imx9_ep0xfer(priv, IMX9_EP0_OUT, NULL, 0); + imx9_ep0state(priv, EP0STATE_WAIT_STATUS_OUT); + break; + + default: +#ifdef CONFIG_DEBUG_FEATURES + DEBUGASSERT(priv->ep0.state != EP0STATE_WAIT_NAK_IN && + priv->ep0.state != EP0STATE_WAIT_NAK_OUT); +#endif + priv->stalled = true; + break; + } + + if (priv->stalled) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_EP0SETUPSTALLED), + priv->ep0.state); + imx9_epstall(&priv->eplist[IMX9_EP0_IN].ep, false); + imx9_epstall(&priv->eplist[IMX9_EP0_OUT].ep, false); + } +} + +/**************************************************************************** + * Name: imx9_epcomplete + * + * Description: + * Transfer complete handler for Endpoints other than 0 + * returns whether the request at the head has completed + * + ****************************************************************************/ + +bool imx9_epcomplete(struct imx9_usb_s *priv, uint8_t epphy) +{ + struct imx9_ep_s *privep = &priv->eplist[epphy]; + struct imx9_req_s *privreq = privep->head; + struct imx9_dtd_s *dtd = &priv->td[epphy]; + + if (privreq == NULL) /* This shouldn't really happen */ + { + if (IMX9_EPPHYOUT(privep->epphy)) + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EPINQEMPTY), 0); + } + else + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EPOUTQEMPTY), 0); + } + + return true; + } + + /* Make sure we have updated data after the DMA transfer. + * This invalidation matches the flush in writedtd(). + */ + + up_invalidate_dcache((uintptr_t)dtd, + (uintptr_t)dtd + sizeof(struct imx9_dtd_s)); + up_invalidate_dcache((uintptr_t)dtd->buffer0, + (uintptr_t)dtd->buffer0 + dtd->xfer_len); + + int xfrd = dtd->xfer_len - (dtd->config >> 16); + + privreq->req.xfrd += xfrd; + + bool complete = true; + if (IMX9_EPPHYOUT(privep->epphy)) + { + /* read(OUT) completes when request filled, or a short transfer is + * received + */ + + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EPIN), complete); + } + else + { + /* write(IN) completes when request finished, unless we need to + * terminate with a ZLP + */ + + bool need_zlp = (xfrd == privep->ep.maxpacket) && + ((privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0); + + complete = (privreq->req.xfrd >= privreq->req.len && !need_zlp); + + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EPOUT), complete); + } + + /* If the transfer is complete, then dequeue and progress any further + * queued requests + */ + + if (complete) + { + privreq = imx9_rqdequeue(privep); + } + + if (!imx9_rqempty(privep)) + { + imx9_progressep(privep); + } + + /* Now it's safe to call the completion callback as it may well submit a + * new request + */ + + if (complete) + { + usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd); + imx9_reqcomplete(privep, privreq, OK); + } + + return complete; +} + +/**************************************************************************** + * Name: imx9_usbinterrupt + * + * Description: + * USB interrupt handler + * + ****************************************************************************/ + +static int imx9_usbinterrupt(int irq, void *context, void *arg) +{ + struct imx9_usb_s *priv = (struct imx9_usb_s *)arg; + uint32_t disr; + uint32_t portsc1; + uint32_t n; + + usbtrace(TRACE_INTENTRY(IMX9_TRACEINTID_USB), 0); + + /* Read the interrupts and then clear them */ + + disr = imx9_getreg(priv, IMX9_USBDEV_USBSTS_OFFSET); + imx9_putreg(priv, IMX9_USBDEV_USBSTS_OFFSET, disr); + + if (disr & USBDEV_USBSTS_URI) + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_DEVRESET), 0); + + imx9_usbreset(priv); + + usbtrace(TRACE_INTEXIT(IMX9_TRACEINTID_USB), 0); + return OK; + } + + /* When the device controller enters a suspend state from an active state, + * the SLI bit will be set to a one. + */ + + if (!priv->suspended && (disr & USBDEV_USBSTS_SLI) != 0) + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_SUSPENDED), 0); + + /* Inform the Class driver of the suspend event */ + + priv->suspended = 1; + if (priv->driver) + { + CLASS_SUSPEND(priv->driver, &priv->usbdev); + } + + /* TODO: Perform power management operations here. */ + } + + /* The device controller clears the SLI bit upon exiting from a suspend + * state. This bit can also be cleared by software writing a one to it. + */ + + else if (priv->suspended && (disr & USBDEV_USBSTS_SLI) == 0) + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_RESUMED), 0); + + /* Inform the Class driver of the resume event */ + + priv->suspended = 0; + if (priv->driver) + { + CLASS_RESUME(priv->driver, &priv->usbdev); + } + + /* TODO: Perform power management operations here. */ + } + + if (disr & USBDEV_USBSTS_PCI) + { + portsc1 = imx9_getreg(priv, IMX9_USBDEV_PORTSC1_OFFSET); + + if (portsc1 & USBDEV_PRTSC1_HSP) + priv->usbdev.speed = USB_SPEED_HIGH; + else + priv->usbdev.speed = USB_SPEED_FULL; + + if (portsc1 & USBDEV_PRTSC1_FPR) + { + /* FIXME: this occurs because of a J-to-K transition detected + * while the port is in SUSPEND state - presumambly this + * is where the host is resuming the device? + * + * - but do we need to "ack" the interrupt + */ + } + } + +#ifdef CONFIG_IMX9_USB_FRAME_INTERRUPT + if (disr & USBDEV_USBSTS_SRI) + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_FRAME), 0); + + uint32_t frindex = imx9_getreg(IMX9_USB_FRINDEX); + uint16_t frame_num = + (frindex & USBDEV_FRINDEX_LFN_MASK) >> USBDEV_FRINDEX_LFN_SHIFT; + + priv->sof = frame_num; + } +#endif + + if (disr & USBDEV_USBSTS_UEI) + { + /* FIXME: these occur when a transfer results in an error condition + * it is set alongside USBINT if the DTD also had its IOC + * bit set. + */ + } + + if (disr & USBDEV_USBSTS_UI) + { + /* Handle completion interrupts */ + + uint32_t mask = imx9_getreg(priv, IMX9_USBDEV_ENDPTCOMPLETE_OFFSET); + + if (mask) + { + /* Clear any NAK interrupt and completion interrupts */ + + imx9_putreg(priv, IMX9_USBDEV_ENDPTNAK_OFFSET, mask); + imx9_putreg(priv, IMX9_USBDEV_ENDPTCOMPLETE_OFFSET, mask); + + if (mask & IMX9_ENDPTMASK(0)) + { + imx9_ep0complete(priv, 0); + } + + if (mask & IMX9_ENDPTMASK(1)) + { + imx9_ep0complete(priv, 1); + } + + for (n = 1; n < IMX9_NLOGENDPOINTS; n++) + { + if (mask & IMX9_ENDPTMASK((n << 1))) + { + imx9_epcomplete(priv, (n << 1)); + } + + if (mask & IMX9_ENDPTMASK((n << 1)+1)) + { + imx9_epcomplete(priv, (n << 1)+1); + } + } + } + + /* Handle setup interrupts */ + + uint32_t setupstat = imx9_getreg(priv, + IMX9_USBDEV_ENDPTSETUPSTAT_OFFSET); + if (setupstat) + { + /* Clear the endpoint complete CTRL OUT and IN when a Setup is + * received + */ + + imx9_putreg(priv, IMX9_USBDEV_ENDPTCOMPLETE_OFFSET, + IMX9_ENDPTMASK(IMX9_EP0_IN) | + IMX9_ENDPTMASK(IMX9_EP0_OUT)); + + if (setupstat & IMX9_ENDPTMASK(IMX9_EP0_OUT)) + { + usbtrace(TRACE_INTDECODE(IMX9_TRACEINTID_EP0SETUP), + setupstat); + imx9_ep0setup(priv); + } + } + } + + if (disr & USBDEV_USBSTS_NAKI) + { + uint32_t pending = imx9_getreg(priv, IMX9_USBDEV_ENDPTNAK_OFFSET) & + imx9_getreg(priv, IMX9_USBDEV_ENDPTNAKEN_OFFSET); + + if (pending) + { + /* We shouldn't see NAK interrupts except on Endpoint 0 */ + + if (pending & IMX9_ENDPTMASK(0)) + { + imx9_ep0nak(priv, 0); + } + + if (pending & IMX9_ENDPTMASK(1)) + { + imx9_ep0nak(priv, 1); + } + } + + /* Clear the interrupts */ + + imx9_putreg(priv, IMX9_USBDEV_ENDPTNAK_OFFSET, pending); + } + + usbtrace(TRACE_INTEXIT(IMX9_TRACEINTID_USB), 0); + return OK; +} + +/**************************************************************************** + * Endpoint operations + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_epconfigure + * + * Description: + * Configure endpoint, making it usable + * + * Input Parameters: + * ep - the struct usbdev_ep_s instance obtained from allocep() + * desc - A struct usb_epdesc_s instance describing the endpoint + * last - true if this is the last endpoint to be configured. Some + * hardware needs to take special action when all of the endpoints + * have been configured. + * + ****************************************************************************/ + +static int imx9_epconfigure(struct usbdev_ep_s *ep, + const struct usb_epdesc_s *desc, + bool last) +{ + struct imx9_ep_s *privep = (struct imx9_ep_s *)ep; + struct imx9_usb_s *priv = privep->dev; + struct imx9_dqh_s *dqh = &priv->qh[privep->epphy]; + + usbtrace(TRACE_EPCONFIGURE, privep->epphy); + DEBUGASSERT(desc->addr == ep->eplog); + + /* Initialise EP capabilities */ + + uint16_t maxsize = GETUINT16(desc->mxpacketsize); + if ((desc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_ISOC) + { + dqh->capability = (DQH_CAPABILITY_MAX_PACKET(maxsize) | + DQH_CAPABILITY_IOS | + DQH_CAPABILITY_ZLT); + } + else + { + dqh->capability = (DQH_CAPABILITY_MAX_PACKET(maxsize) | + DQH_CAPABILITY_ZLT); + } + + up_clean_dcache((uintptr_t)dqh, + (uintptr_t)dqh + sizeof(struct imx9_dqh_s)); + + /* Setup Endpoint Control Register */ + + if (IMX9_EPPHYIN(privep->epphy)) + { + /* Reset the data toggles */ + + uint32_t cfg = USBDEV_ENDPTCTRL_TXR; + + /* Set the endpoint type */ + + switch (desc->attr & USB_EP_ATTR_XFERTYPE_MASK) + { + case USB_EP_ATTR_XFER_CONTROL: + cfg |= USBDEV_ENDPTCTRL_TXT_CTRL; break; + case USB_EP_ATTR_XFER_ISOC: + cfg |= USBDEV_ENDPTCTRL_TXT_ISOC; break; + case USB_EP_ATTR_XFER_BULK: + cfg |= USBDEV_ENDPTCTRL_TXT_BULK; break; + case USB_EP_ATTR_XFER_INT: + cfg |= USBDEV_ENDPTCTRL_TXT_INTR; break; + } + + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL_OFFSET(privep->epphy >> 1), + 0xffff0000, cfg); + } + else + { + /* Reset the data toggles */ + + uint32_t cfg = USBDEV_ENDPTCTRL_RXR; + + /* Set the endpoint type */ + + switch (desc->attr & USB_EP_ATTR_XFERTYPE_MASK) + { + case USB_EP_ATTR_XFER_CONTROL: + cfg |= USBDEV_ENDPTCTRL_RXT_CTRL; break; + case USB_EP_ATTR_XFER_ISOC: + cfg |= USBDEV_ENDPTCTRL_RXT_ISOC; break; + case USB_EP_ATTR_XFER_BULK: + cfg |= USBDEV_ENDPTCTRL_RXT_BULK; break; + case USB_EP_ATTR_XFER_INT: + cfg |= USBDEV_ENDPTCTRL_RXT_INTR; break; + } + + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL_OFFSET(privep->epphy >> 1), + 0xffff0000, cfg); + } + + /* Reset endpoint status */ + + privep->stalled = false; + + /* Enable the endpoint */ + + if (IMX9_EPPHYIN(privep->epphy)) + { + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL_OFFSET(privep->epphy >> 1), + 0, USBDEV_ENDPTCTRL_TXE); + } + else + { + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL_OFFSET(privep->epphy >> 1), + 0, USBDEV_ENDPTCTRL_RXE); + } + + return OK; +} + +/**************************************************************************** + * Name: imx9_epdisable + * + * Description: + * The endpoint will no longer be used + * + ****************************************************************************/ + +static int imx9_epdisable(struct usbdev_ep_s *ep) +{ + struct imx9_ep_s *privep = (struct imx9_ep_s *)ep; + struct imx9_usb_s *priv = privep->dev; + irqstate_t flags; + +#ifdef CONFIG_DEBUG_FEATURES + if (!ep) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + + usbtrace(TRACE_EPDISABLE, privep->epphy); + + flags = enter_critical_section(); + + /* Disable Endpoint */ + + if (IMX9_EPPHYIN(privep->epphy)) + { + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL_OFFSET(privep->epphy >> 1), + USBDEV_ENDPTCTRL_TXE, 0); + } + else + { + imx9_modifyreg(priv, IMX9_USBDEV_ENDPTCTRL_OFFSET(privep->epphy >> 1), + USBDEV_ENDPTCTRL_RXE, 0); + } + + privep->stalled = true; + + /* Cancel any ongoing activity */ + + imx9_cancelrequests(privep, -ESHUTDOWN); + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: imx9_epallocreq + * + * Description: + * Allocate an I/O request + * + ****************************************************************************/ + +static struct usbdev_req_s *imx9_epallocreq(struct usbdev_ep_s *ep) +{ + struct imx9_req_s *privreq; + +#ifdef CONFIG_DEBUG_FEATURES + if (!ep) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_INVALIDPARMS), 0); + return NULL; + } +#endif + + usbtrace(TRACE_EPALLOCREQ, ((struct imx9_ep_s *)ep)->epphy); + + privreq = kmm_malloc(sizeof(struct imx9_req_s)); + if (!privreq) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_ALLOCFAIL), 0); + return NULL; + } + + memset(privreq, 0, sizeof(struct imx9_req_s)); + return &privreq->req; +} + +/**************************************************************************** + * Name: imx9_epfreereq + * + * Description: + * Free an I/O request + * + ****************************************************************************/ + +static void imx9_epfreereq(struct usbdev_ep_s *ep, + struct usbdev_req_s *req) +{ + struct imx9_req_s *privreq = (struct imx9_req_s *)req; + +#ifdef CONFIG_DEBUG_FEATURES + if (!ep || !req) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_INVALIDPARMS), 0); + return; + } +#endif + + usbtrace(TRACE_EPFREEREQ, ((struct imx9_ep_s *)ep)->epphy); + kmm_free(privreq); +} + +/**************************************************************************** + * Name: imx9_epallocbuffer + * + * Description: + * Allocate an I/O buffer + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DMA +static void *imx9_epallocbuffer(struct usbdev_ep_s *ep, uint16_t bytes) +{ + /* The USB peripheral DMA is very forgiving, as the dTD allows the buffer + * to start at any address. Hence, no need for alignment. + */ + + struct imx9_ep_s *privep = (struct imx9_ep_s *)ep; + UNUSED(privep); + + usbtrace(TRACE_EPALLOCBUFFER, privep->epphy); +#ifdef CONFIG_USBDEV_DMAMEMORY + return usbdev_dma_alloc(bytes); +#else + return cache_aligned_alloc(bytes); +#endif +} +#endif + +/**************************************************************************** + * Name: imx9_epfreebuffer + * + * Description: + * Free an I/O buffer + * + ****************************************************************************/ + +#ifdef CONFIG_USBDEV_DMA +static void imx9_epfreebuffer(struct usbdev_ep_s *ep, void *buf) +{ + struct imx9_ep_s *privep = (struct imx9_ep_s *)ep; + UNUSED(privep); + + usbtrace(TRACE_EPFREEBUFFER, privep->epphy); + +#ifdef CONFIG_USBDEV_DMAMEMORY + usbdev_dma_free(buf); +#else + kmm_free(buf); +#endif +} +#endif + +/**************************************************************************** + * Name: imx9_epsubmit + * + * Description: + * Submit an I/O request to the endpoint + * + ****************************************************************************/ + +static int imx9_epsubmit(struct usbdev_ep_s *ep, + struct usbdev_req_s *req) +{ + struct imx9_req_s *privreq = (struct imx9_req_s *)req; + struct imx9_ep_s *privep = (struct imx9_ep_s *)ep; + struct imx9_usb_s *priv; + irqstate_t flags; + int ret = OK; + +#ifdef CONFIG_DEBUG_FEATURES + if (!req || !req->callback || !req->buf || !ep) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_INVALIDPARMS), 0); + uinfo("req=%p callback=%p buf=%p ep=%p\n", req, + req->callback, req->buf, ep); + return -EINVAL; + } +#endif + + usbtrace(TRACE_EPSUBMIT, privep->epphy); + priv = privep->dev; + + if (!priv->driver || priv->usbdev.speed == USB_SPEED_UNKNOWN) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_NOTCONFIGURED), + priv->usbdev.speed); + return -ESHUTDOWN; + } + + /* Handle the request from the class driver */ + + req->result = -EINPROGRESS; + req->xfrd = 0; + + /* Disable Interrupts */ + + flags = enter_critical_section(); + + /* If we are stalled, then drop all requests on the floor */ + + if (privep->stalled) + { + ret = -EBUSY; + } + else + { + /* Add the new request to the request queue for the endpoint */ + + if (IMX9_EPPHYIN(privep->epphy)) + { + usbtrace(TRACE_INREQQUEUED(privep->epphy), privreq->req.len); + } + else + { + usbtrace(TRACE_OUTREQQUEUED(privep->epphy), privreq->req.len); + } + + if (imx9_rqenqueue(privep, privreq)) + { + imx9_progressep(privep); + } + } + + leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Name: imx9_epcancel + * + * Description: + * Cancel an I/O request previously sent to an endpoint + * + ****************************************************************************/ + +static int imx9_epcancel(struct usbdev_ep_s *ep, + struct usbdev_req_s *req) +{ + struct imx9_ep_s *privep = (struct imx9_ep_s *)ep; + irqstate_t flags; + +#ifdef CONFIG_DEBUG_FEATURES + if (!ep || !req) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } +#endif + + usbtrace(TRACE_EPCANCEL, privep->epphy); + + flags = enter_critical_section(); + + /* FIXME: if the request is the first, then we need to flush the EP + * otherwise just remove it from the list + * + * but ... all other implementations cancel all requests ... + */ + + imx9_cancelrequests(privep, -ESHUTDOWN); + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: imx9_epstall + * + * Description: + * Stall or resume and endpoint + * + ****************************************************************************/ + +static int imx9_epstall(struct usbdev_ep_s *ep, bool resume) +{ + struct imx9_ep_s *privep = (struct imx9_ep_s *)ep; + struct imx9_usb_s *priv = privep->dev; + irqstate_t flags; + + /* STALL or RESUME the endpoint */ + + flags = enter_critical_section(); + usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, privep->epphy); + + uint32_t offs = IMX9_USBDEV_ENDPTCTRL_OFFSET(privep->epphy >> 1); + uint32_t ctrl_xs = IMX9_EPPHYIN(privep->epphy) ? + USBDEV_ENDPTCTRL_TXS : USBDEV_ENDPTCTRL_RXS; + uint32_t ctrl_xr = IMX9_EPPHYIN(privep->epphy) ? + USBDEV_ENDPTCTRL_TXR : USBDEV_ENDPTCTRL_RXR; + + if (resume) + { + privep->stalled = false; + + /* Clear stall and reset the data toggle */ + + imx9_modifyreg(priv, offs, ctrl_xs | ctrl_xr, ctrl_xr); + } + else + { + privep->stalled = true; + + imx9_modifyreg(priv, offs, 0, ctrl_xs); + } + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Device operations + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_allocep + * + * Description: + * Allocate an endpoint matching the parameters. + * + * Input Parameters: + * eplog - 7-bit logical endpoint number (direction bit ignored). Zero + * means that any endpoint matching the other requirements will + * suffice. The assigned endpoint can be found in the eplog field. + * in - true: IN (device-to-host) endpoint requested + * eptype - Endpoint type. One of {USB_EP_ATTR_XFER_ISOC, + * USB_EP_ATTR_XFER_BULK, USB_EP_ATTR_XFER_INT} + * + ****************************************************************************/ + +static struct usbdev_ep_s *imx9_allocep(struct usbdev_s *dev, + uint8_t eplog, + bool in, uint8_t eptype) +{ + struct imx9_usb_s *priv = (struct imx9_usb_s *)dev; + uint32_t epset = IMX9_EPALLSET & ~IMX9_EPCTRLSET; + irqstate_t flags; + int epndx = 0; + + usbtrace(TRACE_DEVALLOCEP, (uint16_t)eplog); + + /* Ignore any direction bits in the logical address */ + + eplog = USB_EPNO(eplog); + + /* A logical address of 0 means that any endpoint will do */ + + if (eplog > 0) + { + /* Otherwise, we will return the endpoint structure only for the + * requested 'logical' endpoint. All of the other checks will still be + * performed. + * + * First, verify that the logical endpoint is in the range supported by + * by the hardware. + */ + + if (eplog >= IMX9_NLOGENDPOINTS) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADEPNO), (uint16_t)eplog); + return NULL; + } + + /* Convert the logical address to a physical OUT endpoint address and + * remove all of the candidate endpoints from the bitset except for the + * the IN/OUT pair for this logical address. + */ + + epset &= 3 << (eplog << 1); + } + + /* Get the subset matching the requested direction */ + + if (in) + { + epset &= IMX9_EPINSET; + } + else + { + epset &= IMX9_EPOUTSET; + } + + /* Get the subset matching the requested type */ + + switch (eptype) + { + case USB_EP_ATTR_XFER_INT: /* Interrupt endpoint */ + epset &= IMX9_EPINTRSET; + break; + + case USB_EP_ATTR_XFER_BULK: /* Bulk endpoint */ + epset &= IMX9_EPBULKSET; + break; + + case USB_EP_ATTR_XFER_ISOC: /* Isochronous endpoint */ + epset &= IMX9_EPISOCSET; + break; + + case USB_EP_ATTR_XFER_CONTROL: /* Control endpoint -- not a valid choice */ + default: + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BADEPTYPE), (uint16_t)eptype); + return NULL; + } + + /* Is the resulting endpoint supported by the IMX9? */ + + if (epset) + { + /* Yes.. now see if any of the request endpoints are available */ + + flags = enter_critical_section(); + epset &= priv->epavail; + if (epset) + { + /* Select the lowest bit in the set of matching, available + * endpoints + */ + + for (epndx = 2; epndx < IMX9_NPHYSENDPOINTS; epndx++) + { + uint32_t bit = 1 << epndx; + if ((epset & bit) != 0) + { + /* Mark endpoint no longer available */ + + priv->epavail &= ~bit; + leave_critical_section(flags); + + /* And return the pointer to the standard endpoint + * structure + */ + + return &priv->eplist[epndx].ep; + } + } + + /* Shouldn't get here */ + } + + leave_critical_section(flags); + } + + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_NOEP), (uint16_t)eplog); + return NULL; +} + +/**************************************************************************** + * Name: imx9_freeep + * + * Description: + * Free the previously allocated endpoint + * + ****************************************************************************/ + +static void imx9_freeep(struct usbdev_s *dev, + struct usbdev_ep_s *ep) +{ + struct imx9_usb_s *priv = (struct imx9_usb_s *)dev; + struct imx9_ep_s *privep = (struct imx9_ep_s *)ep; + irqstate_t flags; + + usbtrace(TRACE_DEVFREEEP, (uint16_t)privep->epphy); + + if (priv && privep) + { + /* Mark the endpoint as available */ + + flags = enter_critical_section(); + priv->epavail |= (1 << privep->epphy); + leave_critical_section(flags); + } +} + +/**************************************************************************** + * Name: imx9_getframe + * + * Description: + * Returns the current frame number + * + ****************************************************************************/ + +static int imx9_getframe(struct usbdev_s *dev) +{ + struct imx9_usb_s *priv = (struct imx9_usb_s *)dev; + +#ifdef CONFIG_IMX9_USB_FRAME_INTERRUPT + /* Return last valid value of SOF read by the interrupt handler */ + + usbtrace(TRACE_DEVGETFRAME, (uint16_t)priv->sof); + return priv->sof; +#else + uint32_t frindex = imx9_getreg(priv, IMX9_USBDEV_FRINDEX_OFFSET); + uint16_t frame_num = + (frindex & USBDEV_FRINDEX_LFN_MASK) >> USBDEV_FRINDEX_LFN_SHIFT; + + /* Return the last frame number detected by the hardware */ + + usbtrace(TRACE_DEVGETFRAME, frame_num); + + return (int)(frame_num); +#endif +} + +/**************************************************************************** + * Name: imx9_wakeup + * + * Description: + * Tries to wake up the host connected to this device + * + ****************************************************************************/ + +static int imx9_wakeup(struct usbdev_s *dev) +{ + irqstate_t flags; + struct imx9_usb_s *priv = (struct imx9_usb_s *)dev; + + usbtrace(TRACE_DEVWAKEUP, 0); + + flags = enter_critical_section(); + imx9_modifyreg(priv, IMX9_USBDEV_PORTSC1_OFFSET, 0, USBDEV_PRTSC1_FPR); + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: imx9_selfpowered + * + * Description: + * Sets/clears the device selfpowered feature + * + ****************************************************************************/ + +static int imx9_selfpowered(struct usbdev_s *dev, bool selfpowered) +{ + struct imx9_usb_s *priv = (struct imx9_usb_s *)dev; + + usbtrace(TRACE_DEVSELFPOWERED, (uint16_t)selfpowered); + +#ifdef CONFIG_DEBUG_FEATURES + if (!dev) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_INVALIDPARMS), 0); + return -ENODEV; + } +#endif + + priv->selfpowered = selfpowered; + return OK; +} + +/**************************************************************************** + * Name: imx9_pullup + * + * Description: + * Software-controlled connect to/disconnect from USB host + * + ****************************************************************************/ + +static int imx9_pullup(struct usbdev_s *dev, bool enable) +{ + struct imx9_usb_s *priv = (struct imx9_usb_s *)dev; + + usbtrace(TRACE_DEVPULLUP, (uint16_t)enable); + + irqstate_t flags = enter_critical_section(); + if (enable) + { + imx9_modifyreg(priv, IMX9_USBDEV_USBCMD_OFFSET, 0, USBDEV_USBCMD_RS); + +#ifdef CONFIG_IMX9_USB0DEV_NOVBUS + /* Create a 'false' power event on the USB port so the MAC connects */ + + imx9_modifyreg(priv, IMX9_USBOTG_OTGSC_OFFSET, USBOTG_OTGSC_VD, 0); + imx9_modifyreg(priv, IMX9_USBOTG_OTGSC_OFFSET, 0, USBOTG_OTGSC_VC); +#endif + } + else + { + imx9_modifyreg(priv, IMX9_USBDEV_USBCMD_OFFSET, USBDEV_USBCMD_RS, 0); + } + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_vbus_detect + * + * Description: + * Read the VBUS state from the USB OTG controller. This can be used + * to poll the VBUS state + * + * Input Parameters: + * id: IMX9_USBC1 or IMX9_USBC2 + * + * Returned Value: + * true if VBUS is valid; false otherwise + * + ****************************************************************************/ + +bool imx9_vbus_detect(imx9_usb_id_t id) +{ + int i; + struct imx9_usb_s *priv; + uint32_t otgsc = 0; + + /* Find the correct device to which the driver is bound to */ + + for (i = 0; i < n_usbdevs; i++) + { + if (id == g_usbdev[i].id) + { + break; + } + } + + if (i < n_usbdevs) + { + priv = &g_usbdev[i]; + otgsc = imx9_getreg(priv, IMX9_USBOTG_OTGSC_OFFSET); + } + + return (otgsc & USBOTG_OTGSC_AVV) != 0; +} + +/**************************************************************************** + * Name: arm64_usbinitialize + * + * Description: + * Initialize USB hardware. + * + * Assumptions: + * - This function is called very early in the initialization sequence + * + ****************************************************************************/ + +void arm64_usbinitialize(void) +{ + /* For now, this driver supports just one usb device, either + * USBC1 or USBC2. The configured one is in g_usbdev[0]. + */ + + struct imx9_usb_s *priv = &g_usbdev[0]; + int i; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Initialize the device state structure */ + + priv->usbdev.ops = &g_devops; + priv->usbdev.ep0 = &priv->eplist[IMX9_EP0_IN].ep; + priv->epavail = IMX9_EPALLSET & ~IMX9_EPCTRLSET; + + /* Initialize the endpoint list */ + + for (i = 0; i < IMX9_NPHYSENDPOINTS; i++) + { + uint32_t bit = 1 << i; + + /* Set endpoint operations, reference to driver structure and + * the physical endpoint number (which is just the index to the + * endpoint). + */ + + priv->eplist[i].ep.ops = &g_epops; + priv->eplist[i].dev = priv; + + /* The index, i, is the physical endpoint address; Map this + * to a logical endpoint address usable by the class driver. + */ + + priv->eplist[i].epphy = i; + if (IMX9_EPPHYIN(i)) + { + priv->eplist[i].ep.eplog = IMX9_EPPHYIN2LOG(i); + } + else + { + priv->eplist[i].ep.eplog = IMX9_EPPHYOUT2LOG(i); + } + + /* The maximum packet size may depend on the type of endpoint */ + + if ((IMX9_EPCTRLSET & bit) != 0) + { + priv->eplist[i].ep.maxpacket = IMX9_EP0MAXPACKET; + } + else if ((IMX9_EPINTRSET & bit) != 0) + { + priv->eplist[i].ep.maxpacket = IMX9_INTRMAXPACKET; + } + else if ((IMX9_EPBULKSET & bit) != 0) + { + priv->eplist[i].ep.maxpacket = IMX9_BULKMAXPACKET; + } + else /* if ((IMX9_EPISOCSET & bit) != 0) */ + { + priv->eplist[i].ep.maxpacket = IMX9_ISOCMAXPACKET; + } + } + + /* Clock gate on */ + + imx9_ccm_gate_on(CCM_LPCG_USB_CONTROLLER, true); + + /* Disable USB interrupts */ + + imx9_putreg(priv, IMX9_USBDEV_USBINTR_OFFSET, 0); + + /* Soft reset PHY and enable clock - not needed for on-chip USB2 phy */ + + /* Disconnect device */ + + imx9_pullup(&priv->usbdev, false); + + /* Reset the controller */ + + imx9_modifyreg(priv, IMX9_USBDEV_USBCMD_OFFSET, 0, USBDEV_USBCMD_RST); + while (imx9_getreg(priv, IMX9_USBDEV_USBCMD_OFFSET) & USBDEV_USBCMD_RST); + + /* Power up the PHY - not needed for on-chip USB2 phy */ + + /* Program the controller to be the USB device controller */ + + imx9_putreg(priv, IMX9_USBDEV_USBMODE_OFFSET, + USBDEV_USBMODE_SDIS | USBDEV_USBMODE_SLOM | + USBDEV_USBMODE_CM_DEVICE); + + /* Attach USB controller interrupt handler */ + + irq_attach(IMX9_IRQ_USB1 + priv->id, imx9_usbinterrupt, priv); + up_enable_irq(IMX9_IRQ_USB1 + priv->id); + + leave_critical_section(flags); + + /* Reset/Re-initialize the USB hardware */ + + imx9_usbreset(priv); +} + +/**************************************************************************** + * Name: arm_usbuninitialize + ****************************************************************************/ + +void arm64_usbuninitialize(void) +{ + struct imx9_usb_s *priv = &g_usbdev[0]; + irqstate_t flags; + + usbtrace(TRACE_DEVUNINIT, 0); + + if (priv->driver) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_DRIVERREGISTERED), 0); + usbdev_unregister(priv->driver); + } + + flags = enter_critical_section(); + + /* Disconnect device */ + + imx9_pullup(&priv->usbdev, false); + priv->usbdev.speed = USB_SPEED_UNKNOWN; + + /* Disable and detach IRQs */ + + up_disable_irq(IMX9_IRQ_USB1 + priv->id); + irq_detach(IMX9_IRQ_USB1 + priv->id); + + /* Reset the controller */ + + imx9_modifyreg(priv, IMX9_USBDEV_USBCMD_OFFSET, 0, USBDEV_USBCMD_RST); + while (imx9_getreg(priv, IMX9_USBDEV_USBCMD_OFFSET) & USBDEV_USBCMD_RST); + + /* Turn off USB power and clocking */ + + /* Power down the PHY */ + + /* Clock gate off - NOTE: this turns off the clock from both controllers. + * Add reference counting if expanding this to support several ones. + */ + + imx9_ccm_gate_on(CCM_LPCG_USB_CONTROLLER, false); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: usbdev_register + * + * Description: + * Register a USB device class driver. The class driver's bind() method + * will be called to bind it to a USB device driver. + * + ****************************************************************************/ + +int usbdev_register(struct usbdevclass_driver_s *driver) +{ + int ret; + + usbtrace(TRACE_DEVREGISTER, 0); + +#ifdef CONFIG_DEBUG_FEATURES + if (!driver || !driver->ops->bind || !driver->ops->unbind || + !driver->ops->disconnect || !driver->ops->setup) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_INVALIDPARMS), 0); + return -EINVAL; + } + + if (g_usbdev[0].driver) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_DRIVER), 0); + return -EBUSY; + } +#endif + + /* First hook up the driver */ + + g_usbdev[0].driver = driver; + + /* Then bind the class driver */ + + ret = CLASS_BIND(driver, &g_usbdev[0].usbdev); + if (ret) + { + usbtrace(TRACE_DEVERROR(IMX9_TRACEERR_BINDFAILED), (uint16_t)-ret); + g_usbdev[0].driver = NULL; + } + else + { + /* Enable USB controller interrupts */ + + up_enable_irq(IMX9_IRQ_USB1 + g_usbdev[0].id); + } + + return ret; +} + +/**************************************************************************** + * Name: usbdev_unregister + * + * Description: + * Un-register usbdev class driver.If the USB device is connected to a USB + * host, it will first disconnect(). The driver is also requested to + * unbind() and clean up any device state, before this procedure finally + * returns. + * + ****************************************************************************/ + +int usbdev_unregister(struct usbdevclass_driver_s *driver) +{ + int i; + + usbtrace(TRACE_DEVUNREGISTER, 0); + + /* Find the correct device to which the driver is bound to */ + + for (i = 0; i < n_usbdevs; i++) + { + if (driver == g_usbdev[i].driver) + { + break; + } + } + + if (i == n_usbdevs) + { + return -EINVAL; + } + + /* Unbind the class driver */ + + CLASS_UNBIND(driver, &g_usbdev[i].usbdev); + + /* Disable USB controller interrupts */ + + up_disable_irq(IMX9_IRQ_USB1 + g_usbdev[i].id); + + /* Unhook the driver */ + + g_usbdev[i].driver = NULL; + + return OK; +} + diff --git a/arch/arm64/src/imx9/imx9_usbdev.h b/arch/arm64/src/imx9/imx9_usbdev.h new file mode 100644 index 0000000000000..b18008c3545b5 --- /dev/null +++ b/arch/arm64/src/imx9/imx9_usbdev.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/arm64/src/imx9/imx9_usbdev.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_USBDEV_H +#define __ARCH_ARM64_SRC_IMX9_IMX9_USBDEV_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef enum +{ + IMX9_USBC1 = 0, + IMX9_USBC2 = 1, +} imx9_usb_id_t; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_vbus_detect + * + * Description: + * Read the VBUS state from the USB OTG controller. This can be used + * to poll the VBUS state + * + * Input Parameters: + * id: IMX9_USBC1 or IMX9_USBC2 + * + * Returned Value: + * true if VBUS is valid; false otherwise + * + ****************************************************************************/ + +bool imx9_vbus_detect(imx9_usb_id_t id); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM64_SRC_IMX9_IMX9_USBDEV_H */ diff --git a/arch/risc-v/src/common/riscv_addrenv.c b/arch/risc-v/src/common/riscv_addrenv.c index f26a5d11c2869..42417788c576a 100644 --- a/arch/risc-v/src/common/riscv_addrenv.c +++ b/arch/risc-v/src/common/riscv_addrenv.c @@ -65,6 +65,7 @@ #include #include #include +#include #include @@ -421,6 +422,12 @@ int up_addrenv_create(size_t textsize, size_t datasize, size_t heapsize, heapsize = heapsize + MM_PGALIGNUP(CONFIG_DEFAULT_TASK_STACKSIZE); +#ifdef CONFIG_TLS_ALIGNED + /* Need more stack for TLS alignment */ + + heapsize += MM_PGALIGNUP(2 * TLS_MAXSTACK); +#endif + /* Map the reserved area */ ret = create_region(addrenv, resvbase, resvsize, MMU_UDATA_FLAGS); diff --git a/arch/risc-v/src/common/riscv_addrenv_pgmap.c b/arch/risc-v/src/common/riscv_addrenv_pgmap.c index da9e250e7652f..0d36c1adeb107 100644 --- a/arch/risc-v/src/common/riscv_addrenv_pgmap.c +++ b/arch/risc-v/src/common/riscv_addrenv_pgmap.c @@ -147,6 +147,26 @@ bool up_addrenv_user_vaddr(uintptr_t vaddr) return riscv_uservaddr(vaddr); } +/**************************************************************************** + * Name: up_addrenv_page_wipe + * + * Description: + * Wipe a page of physical memory, first mapping it into kernel virtual + * memory. + * + * Input Parameters: + * page - The page physical address. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void up_addrenv_page_wipe(uintptr_t page) +{ + riscv_pgwipe(page); +} + #ifdef CONFIG_MM_KMAP /**************************************************************************** diff --git a/arch/risc-v/src/common/riscv_exception.c b/arch/risc-v/src/common/riscv_exception.c index f560a60b0a0be..bb81e6066da44 100644 --- a/arch/risc-v/src/common/riscv_exception.c +++ b/arch/risc-v/src/common/riscv_exception.c @@ -31,6 +31,7 @@ #include #include +#include "sched/sched.h" #include "riscv_internal.h" #include "chip.h" @@ -72,6 +73,9 @@ static const char *g_reasons_str[RISCV_MAX_EXCEPTION + 1] = int riscv_exception(int mcause, void *regs, void *args) { +#ifdef CONFIG_ARCH_KERNEL_STACK + FAR struct tcb_s *tcb = this_task(); +#endif uintptr_t cause = mcause & RISCV_IRQ_MASK; _alert("EXCEPTION: %s. MCAUSE: %" PRIxREG ", EPC: %" PRIxREG @@ -79,10 +83,33 @@ int riscv_exception(int mcause, void *regs, void *args) mcause > RISCV_MAX_EXCEPTION ? "Unknown" : g_reasons_str[cause], cause, READ_CSR(CSR_EPC), READ_CSR(CSR_TVAL)); - _alert("PANIC!!! Exception = %" PRIxREG "\n", cause); - up_irq_save(); - CURRENT_REGS = regs; - PANIC_WITH_REGS("panic", regs); +#ifdef CONFIG_ARCH_KERNEL_STACK + if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) + { + _alert("Segmentation fault in PID %d: %s\n", tcb->pid, tcb->name); + + tcb->flags |= TCB_FLAG_FORCED_CANCEL; + + /* Return to _exit function in privileged mode with argument SIGSEGV */ + + CURRENT_REGS[REG_EPC] = (uintptr_t)_exit; + CURRENT_REGS[REG_A0] = SIGSEGV; + CURRENT_REGS[REG_INT_CTX] |= STATUS_PPP; + + /* Continue with kernel stack in use. The frame(s) in kernel stack + * are no longer needed, so just set it to top + */ + + CURRENT_REGS[REG_SP] = (uintptr_t)tcb->xcp.ktopstk; + } + else +#endif + { + _alert("PANIC!!! Exception = %" PRIxREG "\n", cause); + up_irq_save(); + CURRENT_REGS = regs; + PANIC_WITH_REGS("panic", regs); + } return 0; } diff --git a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c index 88d8be77ee2e3..d1bf8503b4c0e 100644 --- a/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c +++ b/arch/risc-v/src/common/supervisor/riscv_perform_syscall.c @@ -28,6 +28,7 @@ #include +#include "sched/sched.h" #include "riscv_internal.h" /**************************************************************************** @@ -59,6 +60,12 @@ void *riscv_perform_syscall(uintptr_t *regs) if (regs != CURRENT_REGS) { + /* Record the new "running" task. g_running_tasks[] is only used by + * assertion logic for reporting crashes. + */ + + g_running_tasks[this_cpu()] = this_task(); + /* Restore the cpu lock */ restore_critical_section(); diff --git a/arch/risc-v/src/mpfs/.gitignore b/arch/risc-v/src/mpfs/.gitignore new file mode 100644 index 0000000000000..b099a95f78380 --- /dev/null +++ b/arch/risc-v/src/mpfs/.gitignore @@ -0,0 +1 @@ +/crypto diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 9ba677b2acf52..4e9b9194b4e09 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -252,15 +252,48 @@ config MPFS_HAVE_UART4 select UART4_SERIALDRIVER select ARCH_HAVE_SERIAL_TERMIOS +config MPFS_HAVE_UART5 + bool + depends on MPFS_FPGA_UART + default n + select UART5_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +config MPFS_HAVE_UART6 + bool + depends on MPFS_FPGA_UART + default n + select UART6_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +config MPFS_HAVE_UART7 + bool + depends on MPFS_FPGA_UART + default n + select UART7_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + # These are the peripheral selections proper +config MPFS_SPI + bool + default n + config MPFS_SPI0 bool "SPI 0" default n + select MPFS_SPI config MPFS_SPI1 bool "SPI 1" default n + select MPFS_SPI + +config MPFS_FPGA_UART + bool "FPGA uarts" + default n + ---help--- + Use FPGA UARTs instead of MSS UARTS. config MPFS_UART0 bool "UART 0" @@ -297,6 +330,30 @@ config MPFS_UART4 select ARCH_HAVE_SERIAL_TERMIOS select MPFS_HAVE_UART4 +config MPFS_UART5 + bool "UART 5" + depends on MPFS_FPGA_UART + default n + select ARCH_HAVE_UART5 + select ARCH_HAVE_SERIAL_TERMIOS + select MPFS_HAVE_UART5 + +config MPFS_UART6 + bool "UART 6" + depends on MPFS_FPGA_UART + default n + select ARCH_HAVE_UART6 + select ARCH_HAVE_SERIAL_TERMIOS + select MPFS_HAVE_UART6 + +config MPFS_UART7 + bool "UART 7" + depends on MPFS_FPGA_UART + default n + select ARCH_HAVE_UART7 + select ARCH_HAVE_SERIAL_TERMIOS + select MPFS_HAVE_UART7 + config MPFS_I2C0 bool "I2C 0" select ARCH_HAVE_I2CRESET @@ -369,6 +426,12 @@ config MPFS_COREMMC_IRQNUM range 0 63 depends on MPFS_COREMMC +config MPFS_TAMPER + bool "Tamper detection" + default n + ---help--- + Enable tamper detection mechanisms. + config MPFS_IHC_CLIENT bool "IHC slave" depends on RPTUN && !MPFS_BOOTLOADER @@ -410,7 +473,7 @@ config MPFS_IHC_LINUX_ON_HART3 config MPFS_IHC_LINUX_ON_HART4 int "Linux on hart4" depends on MPFS_IHC_CLIENT || MPFS_IHC_SBI - default 1 + default 0 range 0 1 ---help--- Set this to 1 if U-boot / Linux is running on hart4 @@ -577,12 +640,6 @@ config MPFS_COREPWM0_BASE default 0x44000000 depends on MPFS_COREPWM0 -config MPFS_COREPWM0_PWMCLK - int "Clock frequency of the CorePWM0 block (Hz)" - default 25000000 - range 1000000 100000000 - depends on MPFS_COREPWM0 - config MPFS_COREPWM0_REGWIDTH int "Width of the PWM register (8, 16 or 32 bits)" default 32 @@ -606,12 +663,6 @@ config MPFS_COREPWM1_BASE default 0x45000000 depends on MPFS_COREPWM1 -config MPFS_COREPWM1_PWMCLK - int "Clock frequency of the CorePWM1 block (Hz)" - default 25000000 - range 1000000 100000000 - depends on MPFS_COREPWM1 - config MPFS_COREPWM1_REGWIDTH int "Width of the PWM register (8, 16 or 32 bits)" default 32 @@ -624,6 +675,56 @@ config MPFS_COREPWM1_NCHANNELS range 1 16 depends on MPFS_COREPWM1 +comment "CAN-FD Options" + +config MPFS_HAVE_CANFD + bool "CAN FD" + select ARCH_HAVE_CAN_ERRORS + select NET_CAN_HAVE_CANFD + select NET_CAN_EXTID + select NET_CAN_HAVE_TX_DEADLINE + default n + +config MPFS_CANFD0 + bool "MPFS FPGA CANFD0 IP block configured" + default n + depends on MPFS_HAVE_CANFD + +config MPFS_CANFD_BASE0 + hex "Base address for the CANFD0 instance" + default 0x46000000 + depends on MPFS_CANFD0 + +config MPFS_CANFD_ARBI_BITRATE0 + int "CANFD0 Arbitration phase bitrate" + default 1000000 + depends on MPFS_CANFD0 + +config MPFS_CANFD_DATA_BITRATE0 + int "CANFD0 Data phase bitrate" + default 4000000 + depends on MPFS_CANFD0 + +config MPFS_CANFD1 + bool "MPFS FPGA CANFD1 IP block configured" + default n + depends on MPFS_HAVE_CANFD + +config MPFS_CANFD_BASE1 + hex "Base address for the CANFD1 instance" + default 0x47000000 + depends on MPFS_CANFD1 + +config MPFS_CANFD_ARBI_BITRATE1 + int "CANFD1 Arbitration phase bitrate" + default 1000000 + depends on MPFS_CANFD1 + +config MPFS_CANFD_DATA_BITRATE1 + int "CANFD1 Data phase bitrate" + default 4000000 + depends on MPFS_CANFD1 + endmenu config MPFS_DMA @@ -751,6 +852,20 @@ endchoice # GMAC speed endif # !MPFS_MAC_AUTONEG +config MPFS_ETHMAC_HPWORK + bool "Use HP workqueue" + default n + depends on MPFS_ETHMAC + ---help--- + Select HPWORK workqueue for eth ISR work + +config MPFS_ETHMAC_LPWORK + bool "Use LP workqueue" + default n + depends on MPFS_ETHMAC + ---help--- + Select LPWORK workqueue for eth ISR work + config MPFS_ETHMAC_MDC_CLOCK_SOURCE_HZ int "MDC Clock Source (Hz)" default 125000000 @@ -791,6 +906,12 @@ config MPFS_ETHMAC_REGDEBUG endmenu +config MPFS_MPUCFG + bool "Enable MPUCFG driver" + default n + ---help--- + Enable driver to set MPUCFG entries. + config MPFS_HAVE_CORERMII bool "CoreRMII FPGA IP block configured" default n @@ -799,3 +920,13 @@ config MPFS_CORERMII_ADDRESS int "CoreRMII Phy address" default 1 depends on MPFS_HAVE_CORERMII + +config MPFS_CRYPTO + bool "Enable MPFS HW crypto" + default n + +if MPFS_CRYPTO +config MPFS_CRYPTO_DMA + bool "Enable MPFS HW crypto DMA" + default y +endif diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index 6e060cef60e07..027277a5d0960 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -50,7 +50,7 @@ ifeq ($(CONFIG_MM_PGALLOC),y) CHIP_CSRCS += mpfs_pgalloc.c endif -ifeq ($(CONFIG_SPI),y) +ifeq ($(CONFIG_MPFS_SPI),y) CHIP_CSRCS += mpfs_spi.c endif @@ -58,6 +58,10 @@ ifeq ($(CONFIG_I2C),y) CHIP_CSRCS += mpfs_i2c.c endif +ifneq ($(filter y,$(CONFIG_MPFS_EMMCSD) $(CONFIG_MPFS_COREMMC)),) +CHIP_CSRCS += mpfs_sdio.c +endif + ifeq ($(CONFIG_MPFS_EMMCSD),y) CHIP_CSRCS += mpfs_emmcsd.c endif @@ -78,6 +82,10 @@ ifeq (${CONFIG_MPFS_HAVE_COREPWM},y) CHIP_CSRCS += mpfs_corepwm.c endif +ifeq (${CONFIG_MPFS_HAVE_CANFD}, y) +CHIP_CSRCS += mpfs_fpga_canfd.c +endif + ifeq (${CONFIG_MPFS_DDR_INIT},y) CHIP_CSRCS += mpfs_ddr.c endif @@ -108,3 +116,14 @@ ifeq ($(CONFIG_MPFS_CORESPI),y) CHIP_CSRCS += mpfs_corespi.c endif +ifeq ($(CONFIG_MPFS_TAMPER),y) +CHIP_CSRCS += mpfs_tamper.c +endif + +ifeq ($(CONFIG_MPFS_CRYPTO),y) +include mpfs/crypto.defs +endif + +ifeq ($(CONFIG_MPFS_MPUCFG),y) +CHIP_CSRCS += mpfs_mpu.c +endif diff --git a/arch/risc-v/src/mpfs/crypto.defs b/arch/risc-v/src/mpfs/crypto.defs new file mode 100644 index 0000000000000..98f5c330e65c1 --- /dev/null +++ b/arch/risc-v/src/mpfs/crypto.defs @@ -0,0 +1,14 @@ +MPFS_CRYPTO = mpfs/crypto/.git +$(MPFS_CRYPTO): + $(Q) echo "Symlink PolarFire crypto driver submodule" + $(Q) $(DIRLINK) $(CURDIR)/../../../../extern/pf_crypto mpfs/crypto + +context::$(MPFS_CRYPTO) + +distclean:: + $(Q) rm -rf mpfs/crypto + +CHIP_CSRCS += mpfs_crypto.c mpfs_systemservice.c + +DEPPATH += --dep-path mpfs/crypto +VPATH += :mpfs/crypto diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_clint.h b/arch/risc-v/src/mpfs/hardware/mpfs_clint.h index a15d849267902..d398cca8dbd71 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_clint.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_clint.h @@ -21,6 +21,12 @@ #ifndef __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_CLINT_H #define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_CLINT_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mpfs_memorymap.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h b/arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h new file mode 100644 index 0000000000000..16587add2d226 --- /dev/null +++ b/arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h @@ -0,0 +1,472 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_FPGA_CANFD_H +#define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_FPGA_CANFD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/mpfs_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define MPFS_CANFD_DEVICE_ID_OFFSET (0x00) +#define MPFS_CANFD_VERSION_OFFSET (0x02) + +#define MPFS_CANFD_MODE_OFFSET (0x04) +#define MPFS_CANFD_SETTINGS_OFFSET (0x06) + +#define MPFS_CANFD_STATUS_OFFSET (0x08) + +#define MPFS_CANFD_COMMAND_OFFSET (0x0c) + +#define MPFS_CANFD_INT_STAT_OFFSET (0x10) + +#define MPFS_CANFD_INT_ENA_SET_OFFSET (0x14) + +#define MPFS_CANFD_INT_ENA_CLR_OFFSET (0x18) + +#define MPFS_CANFD_INT_MASK_SET_OFFSET (0x1c) + +#define MPFS_CANFD_INT_MASK_CLR_OFFSET (0x20) + +#define MPFS_CANFD_BTR_OFFSET (0x24) + +#define MPFS_CANFD_BTR_FD_OFFSET (0x28) + +#define MPFS_CANFD_EWL_OFFSET (0x2c) +#define MPFS_CANFD_ERP_OFFSET (0x2d) +#define MPFS_CANFD_FAULT_STATE_OFFSET (0x2e) + +#define MPFS_CANFD_REC_OFFSET (0x30) +#define MPFS_CANFD_TEC_OFFSET (0x32) + +#define MPFS_CANFD_ERR_NORM_OFFSET (0x34) +#define MPFS_CANFD_ERR_FD_OFFSET (0x36) + +#define MPFS_CANFD_CTR_PRES_OFFSET (0x38) + +#define MPFS_CANFD_FILTER_A_MASK_OFFSET (0x3c) + +#define MPFS_CANFD_FILTER_A_VAL_OFFSET (0x40) + +#define MPFS_CANFD_FILTER_B_MASK_OFFSET (0x44) + +#define MPFS_CANFD_FILTER_B_VAL_OFFSET (0x48) + +#define MPFS_CANFD_FILTER_C_MASK_OFFSET (0x4c) + +#define MPFS_CANFD_FILTER_C_VAL_OFFSET (0x50) + +#define MPFS_CANFD_FILTER_RAN_LOW_OFFSET (0x54) + +#define MPFS_CANFD_FILTER_RAN_HIGH_OFFSET (0x58) + +#define MPFS_CANFD_FILTER_CONTROL_OFFSET (0x5c) +#define MPFS_CANFD_FILTER_STATUS_OFFSET (0x5e) + +/* RX registers */ +#define MPFS_CANFD_RX_MEM_INFO_OFFSET (0x60) + +#define MPFS_CANFD_RX_POINTERS_OFFSET (0x64) + +#define MPFS_CANFD_RX_STATUS_OFFSET (0x68) +#define MPFS_CANFD_RX_SETTINGS_OFFSET (0x6a) + +#define MPFS_CANFD_RX_DATA_OFFSET (0x6c) + +/* TX registers */ +#define MPFS_CANFD_TX_STATUS_OFFSET (0x70) + +#define MPFS_CANFD_TX_COMMAND_OFFSET (0x74) +#define MPFS_CANFD_TXTB_INFO_OFFSET (0x76) + +#define MPFS_CANFD_TX_PRIORITY_OFFSET (0x78) + +#define MPFS_CANFD_ERR_CAPT_OFFSET (0x7c) +#define MPFS_CANFD_RETR_CTR_OFFSET (0x7d) +#define MPFS_CANFD_ALC_OFFSET (0x7e) + +#define MPFS_CANFD_TRV_DELAY_OFFSET (0x80) +#define MPFS_CANFD_SSP_CFG_OFFSET (0x82) + +#define MPFS_CANFD_RX_FR_CTR_OFFSET (0x84) + +#define MPFS_CANFD_TX_FR_CTR_OFFSET (0x88) + +#define MPFS_CANFD_DEBUG_REGISTER_OFFSET (0x8c) + +#define MPFS_CANFD_YOLO_OFFSET (0x90) + +#define MPFS_CANFD_TIMESTAMP_LOW_OFFSET (0x94) + +#define MPFS_CANFD_TIMESTAMP_HIGH_OFFSET (0x98) + +# define MPFS_CANFD_CTUCANFD_TXTB1_DATA_1 (0x100) +# define MPFS_CANFD_CTUCANFD_TXTB1_DATA_2 (0x104) +# define MPFS_CANFD_CTUCANFD_TXTB1_DATA_20 (0x14c) + +# define MPFS_CANFD_CTUCANFD_TXTB2_DATA_1 (0x200) +# define MPFS_CANFD_CTUCANFD_TXTB2_DATA_2 (0x204) +# define MPFS_CANFD_CTUCANFD_TXTB2_DATA_20 (0x24c) + +# define MPFS_CANFD_CTUCANFD_TXTB3_DATA_1 (0x300) +# define MPFS_CANFD_CTUCANFD_TXTB3_DATA_2 (0x304) +# define MPFS_CANFD_CTUCANFD_TXTB3_DATA_20 (0x34c) + +# define MPFS_CANFD_CTUCANFD_TXTB4_DATA_1 (0x400) +# define MPFS_CANFD_CTUCANFD_TXTB4_DATA_2 (0x404) +# define MPFS_CANFD_CTUCANFD_TXTB4_DATA_20 (0x44c) + +# define MPFS_CANFD_CTUCANFD_TXTB5_DATA_1 (0x500) +# define MPFS_CANFD_CTUCANFD_TXTB5_DATA_2 (0x504) +# define MPFS_CANFD_CTUCANFD_TXTB5_DATA_20 (0x54c) + +# define MPFS_CANFD_CTUCANFD_TXTB6_DATA_1 (0x600) +# define MPFS_CANFD_CTUCANFD_TXTB6_DATA_2 (0x604) +# define MPFS_CANFD_CTUCANFD_TXTB6_DATA_20 (0x64c) + +# define MPFS_CANFD_CTUCANFD_TXTB7_DATA_1 (0x700) +# define MPFS_CANFD_CTUCANFD_TXTB7_DATA_2 (0x704) +# define MPFS_CANFD_CTUCANFD_TXTB7_DATA_20 (0x74c) + +# define MPFS_CANFD_CTUCANFD_TXTB8_DATA_1 (0x800) +# define MPFS_CANFD_CTUCANFD_TXTB8_DATA_2 (0x804) +# define MPFS_CANFD_CTUCANFD_TXTB8_DATA_20 (0x84c) + +# define MPFS_CANFD_CTUCANFD_TST_CONTROL (0x900) +# define MPFS_CANFD_CTUCANFD_TST_DEST (0x904) +# define MPFS_CANFD_CTUCANFD_TST_WDATA (0x908) +# define MPFS_CANFD_CTUCANFD_TST_RDATA (0x90c) + +/* Control_registers memory region ******************************************/ + +/* DEVICE ID / VERSION registers */ +#define MPFS_CANFD_DEVICE_ID_DEVICE_ID_SHIFT (0) +#define MPFS_CANFD_DEVICE_ID_DEVICE_ID (0xffff << MPFS_CANFD_DEVICE_ID_DEVICE_ID_SHIFT) +#define MPFS_CANFD_DEVICE_ID_VER_MINOR_SHIFT (16) +#define MPFS_CANFD_DEVICE_ID_VER_MINOR (0xff << MPFS_CANFD_DEVICE_ID_VER_MINOR_SHIFT) +#define MPFS_CANFD_DEVICE_ID_VER_MAJOR_SHIFT (24) +#define MPFS_CANFD_DEVICE_ID_VER_MAJOR (0xff << MPFS_CANFD_DEVICE_ID_VER_MAJOR_SHIFT) + +/* MODE / SETTINGS registers */ +#define MPFS_CANFD_MODE_RST (1 << 0) +#define MPFS_CANFD_MODE_BMM (1 << 1) +#define MPFS_CANFD_MODE_STM (1 << 2) +#define MPFS_CANFD_MODE_AFM (1 << 3) +#define MPFS_CANFD_MODE_FDE (1 << 4) +#define MPFS_CANFD_MODE_TTTM (1 << 5) +#define MPFS_CANFD_MODE_ROM (1 << 6) +#define MPFS_CANFD_MODE_ACF (1 << 7) +#define MPFS_CANFD_MODE_TSTM (1 << 8) +#define MPFS_CANFD_MODE_RXBAM (1 << 9) +#define MPFS_CANFD_MODE_RTRLE (1 << 16) +#define MPFS_CANFD_MODE_RTRTH_SHIFT (17) +#define MPFS_CANFD_MODE_RTRTH (0x0f << MPFS_CANFD_MODE_RTRTH_SHIFT) +#define MPFS_CANFD_MODE_ILBP (1 << 21) +#define MPFS_CANFD_MODE_ENA (1 << 22) +#define MPFS_CANFD_MODE_NISOFD (1 << 23) +#define MPFS_CANFD_MODE_PEX (1 << 24) +#define MPFS_CANFD_MODE_TBFBO (1 << 25) +#define MPFS_CANFD_MODE_FDRF (1 << 26) + +/* STATUS registers */ +#define MPFS_CANFD_STATUS_RXNE (1 << 0) +#define MPFS_CANFD_STATUS_DOR (1 << 1) +#define MPFS_CANFD_STATUS_TXNF (1 << 2) +#define MPFS_CANFD_STATUS_EFT (1 << 3) +#define MPFS_CANFD_STATUS_RXS (1 << 4) +#define MPFS_CANFD_STATUS_TXS (1 << 5) +#define MPFS_CANFD_STATUS_EWL (1 << 6) +#define MPFS_CANFD_STATUS_IDLE (1 << 7) +#define MPFS_CANFD_STATUS_PEXS (1 << 8) +#define MPFS_CANFD_STATUS_STCNT (1 << 16) +#define MPFS_CANFD_STATUS_STRGS (1 << 17) + +/* COMMAND registers */ +#define MPFS_CANFD_COMMAND_RXRPMV (1 << 1) +#define MPFS_CANFD_COMMAND_RRB (1 << 2) +#define MPFS_CANFD_COMMAND_CDO (1 << 3) +#define MPFS_CANFD_COMMAND_ERCRST (1 << 4) +#define MPFS_CANFD_COMMAND_RXFCRST (1 << 5) +#define MPFS_CANFD_COMMAND_TXFCRST (1 << 6) +#define MPFS_CANFD_COMMAND_CPEXS (1 << 7) + +/* INT_STAT registers */ +#define MPFS_CANFD_INT_STAT_RXI (1 << 0) +#define MPFS_CANFD_INT_STAT_TXI (1 << 1) +#define MPFS_CANFD_INT_STAT_EWLI (1 << 2) +#define MPFS_CANFD_INT_STAT_DOI (1 << 3) +#define MPFS_CANFD_INT_STAT_FCSI (1 << 4) +#define MPFS_CANFD_INT_STAT_ALI (1 << 5) +#define MPFS_CANFD_INT_STAT_BEI (1 << 6) +#define MPFS_CANFD_INT_STAT_OFI (1 << 7) +#define MPFS_CANFD_INT_STAT_RXFI (1 << 8) +#define MPFS_CANFD_INT_STAT_BSI (1 << 9) +#define MPFS_CANFD_INT_STAT_RBNEI (1 << 10) +#define MPFS_CANFD_INT_STAT_TXBHCI (1 << 11) + +/* INT_ENA_SET registers */ +#define MPFS_CANFD_INT_ENA_SET_INT_ENA_SET (0x0fff << 0) + +/* INT_ENA_CLR registers */ +#define MPFS_CANFD_INT_ENA_CLR_INT_ENA_CLR (0x0fff << 0) + +/* INT_MASK_SET registers */ +#define MPFS_CANFD_INT_MASK_SET_INT_MASK_SET (0x0fff << 0) + +/* INT_MASK_CLR registers */ +#define MPFS_CANFD_INT_MASK_CLR_INT_MASK_CLR (0x0fff << 0) + +/* BTR registers */ +#define MPFS_CANFD_BTR_PROP_SHIFT (0) +#define MPFS_CANFD_BTR_PROP (0x7f << MPFS_CANFD_BTR_PROP_SHIFT) +#define MPFS_CANFD_BTR_PH1_SHIFT (7) +#define MPFS_CANFD_BTR_PH1 (0x3f << MPFS_CANFD_BTR_PH1_SHIFT) +#define MPFS_CANFD_BTR_PH2_SHIFT (13) +#define MPFS_CANFD_BTR_PH2 (0x3f << MPFS_CANFD_BTR_PH2_SHIFT) +#define MPFS_CANFD_BTR_BRP_SHIFT (19) +#define MPFS_CANFD_BTR_BRP (0xff << MPFS_CANFD_BTR_BRP_SHIFT) +#define MPFS_CANFD_BTR_SJW_SHIFT (27) +#define MPFS_CANFD_BTR_SJW (0x1f << MPFS_CANFD_BTR_SJW_SHIFT) + +/* BTR_FD registers */ +#define MPFS_CANFD_BTR_FD_PROP_FD_SHIFT (0) +#define MPFS_CANFD_BTR_FD_PROP_FD (0x3f << MPFS_CANFD_BTR_FD_PROP_FD_SHIFT) +#define MPFS_CANFD_BTR_FD_PH1_FD_SHIFT (7) +#define MPFS_CANFD_BTR_FD_PH1_FD (0x1f << MPFS_CANFD_BTR_FD_PH1_FD_SHIFT) +#define MPFS_CANFD_BTR_FD_PH2_FD_SHIFT (13) +#define MPFS_CANFD_BTR_FD_PH2_FD (0x1f << MPFS_CANFD_BTR_FD_PH2_FD_SHIFT) +#define MPFS_CANFD_BTR_FD_BRP_FD_SHIFT (19) +#define MPFS_CANFD_BTR_FD_BRP_FD (0xff << MPFS_CANFD_BTR_FD_BRP_FD_SHIFT) +#define MPFS_CANFD_BTR_FD_SJW_FD_SHIFT (27) +#define MPFS_CANFD_BTR_FD_SJW_FD (0x1f << MPFS_CANFD_BTR_FD_SJW_FD_SHIFT) + +/* EWL / ERP / FAULT_STATE registers */ +#define MPFS_CANFD_EWL_EW_LIMIT_SHIFT (0) +#define MPFS_CANFD_EWL_EW_LIMIT (0xff << MPFS_CANFD_EWL_EW_LIMIT_SHIFT) +#define MPFS_CANFD_EWL_ERP_LIMIT_SHIFT (8) +#define MPFS_CANFD_EWL_ERP_LIMIT (0xff << MPFS_CANFD_EWL_ERP_LIMIT_SHIFT) +#define MPFS_CANFD_EWL_ERA (1 << 16) +#define MPFS_CANFD_EWL_ERP (1 << 17) +#define MPFS_CANFD_EWL_BOF (1 << 18) + +/* REC / TEC registers */ +#define MPFS_CANFD_REC_REC_VAL_SHIFT (0) +#define MPFS_CANFD_REC_REC_VAL (0x01ff << MPFS_CANFD_REC_REC_VAL_SHIFT) +#define MPFS_CANFD_REC_TEC_VAL_SHIFT (16) +#define MPFS_CANFD_REC_TEC_VAL (0x01ff << MPFS_CANFD_REC_TEC_VAL_SHIFT) + +/* ERR_NORM ERR_FD registers */ +#define MPFS_CANFD_ERR_NORM_ERR_NORM_VAL_SHIFT (0) +#define MPFS_CANFD_ERR_NORM_ERR_NORM_VAL (0xffff << MPFS_CANFD_ERR_NORM_ERR_NORM_VAL_SHIFT) +#define MPFS_CANFD_ERR_NORM_ERR_FD_VAL_SHIFT (16) +#define MPFS_CANFD_ERR_NORM_ERR_FD_VAL (0xffff << MPFS_CANFD_ERR_NORM_ERR_FD_VAL_SHIFT) + +/* CTR_PRES registers */ +#define MPFS_CANFD_CTR_PRES_CTPV_SHIFT (0) +#define MPFS_CANFD_CTR_PRES_CTPV (0x01ff << MPFS_CANFD_CTR_PRES_CTPV_SHIFT) +#define MPFS_CANFD_CTR_PRES_PTX (1 << 9) +#define MPFS_CANFD_CTR_PRES_PRX (1 << 10) +#define MPFS_CANFD_CTR_PRES_ENORM (1 << 11) +#define MPFS_CANFD_CTR_PRES_EFD (1 << 12) + +/* FILTER_A_MASK registers */ +#define MPFS_CANFD_FILTER_A_MASK_BIT_MASK_A_VAL (0x1fffffff << 0) + +/* FILTER_A_VAL registers */ +#define MPFS_CANFD_FILTER_A_VAL_BIT_VAL_A_VAL (0x1fffffff << 0) + +/* FILTER_B_MASK registers */ +#define MPFS_CANFD_FILTER_B_MASK_BIT_MASK_B_VAL (0x1fffffff << 0) + +/* FILTER_B_VAL registers */ +#define MPFS_CANFD_FILTER_B_VAL_BIT_VAL_B_VAL (0x1fffffff << 0) + +/* FILTER_C_MASK registers */ +#define MPFS_CANFD_FILTER_C_MASK_BIT_MASK_C_VAL (0x1fffffff << 0) + +/* FILTER_C_VAL registers */ +#define MPFS_CANFD_FILTER_C_VAL_BIT_VAL_C_VAL (0x1fffffff << 0) + +/* FILTER_RAN_LOW registers */ +#define MPFS_CANFD_FILTER_RAN_LOW_BIT_RAN_LOW_VAL (0x1fffffff << 0) + +/* FILTER_RAN_HIGH registers */ +#define MPFS_CANFD_FILTER_RAN_HIGH_BIT_RAN_HIGH_VAL (0x1fffffff << 0) + +/* FILTER_CONTROL / FILTER_STATUS registers */ +#define MPFS_CANFD_FILTER_CONTROL_FANB (1 << 0) +#define MPFS_CANFD_FILTER_CONTROL_FANE (1 << 1) +#define MPFS_CANFD_FILTER_CONTROL_FAFB (1 << 2) +#define MPFS_CANFD_FILTER_CONTROL_FAFE (1 << 3) +#define MPFS_CANFD_FILTER_CONTROL_FBNB (1 << 4) +#define MPFS_CANFD_FILTER_CONTROL_FBNE (1 << 5) +#define MPFS_CANFD_FILTER_CONTROL_FBFB (1 << 6) +#define MPFS_CANFD_FILTER_CONTROL_FBFE (1 << 7) +#define MPFS_CANFD_FILTER_CONTROL_FCNB (1 << 8) +#define MPFS_CANFD_FILTER_CONTROL_FCNE (1 << 9) +#define MPFS_CANFD_FILTER_CONTROL_FCFB (1 << 10) +#define MPFS_CANFD_FILTER_CONTROL_FCFE (1 << 11) +#define MPFS_CANFD_FILTER_CONTROL_FRNB (1 << 12) +#define MPFS_CANFD_FILTER_CONTROL_FRNE (1 << 13) +#define MPFS_CANFD_FILTER_CONTROL_FRFB (1 << 14) +#define MPFS_CANFD_FILTER_CONTROL_FRFE (1 << 15) +#define MPFS_CANFD_FILTER_CONTROL_SFA (1 << 16) +#define MPFS_CANFD_FILTER_CONTROL_SFB (1 << 17) +#define MPFS_CANFD_FILTER_CONTROL_SFC (1 << 18) +#define MPFS_CANFD_FILTER_CONTROL_SFR (1 << 19) + +/* RX_MEM_INFO registers */ +#define MPFS_CANFD_RX_MEM_INFO_RX_BUFF_SIZE_SHIFT (0) +#define MPFS_CANFD_RX_MEM_INFO_RX_BUFF_SIZE (0x1fff << MPFS_CANFD_RX_MEM_INFO_RX_BUFF_SIZE_SHIFT) +#define MPFS_CANFD_RX_MEM_INFO_RX_MEM_FREE_SHIFT (16) +#define MPFS_CANFD_RX_MEM_INFO_RX_MEM_FREE (0x1fff << MPFS_CANFD_RX_MEM_INFO_RX_MEM_FREE_SHIFT) + +/* RX_POINTERS registers */ +#define MPFS_CANFD_RX_POINTERS_RX_WPP_SHIFT (0) +#define MPFS_CANFD_RX_POINTERS_RX_WPP (0x0fff << MPFS_CANFD_RX_POINTERS_RX_WPP_SHIFT) +#define MPFS_CANFD_RX_POINTERS_RX_RPP_SHIFT (16) +#define MPFS_CANFD_RX_POINTERS_RX_RPP (0x0fff << MPFS_CANFD_RX_POINTERS_RX_RPP_SHIFT) + +/* RX_STATUS / RX_SETTINGS registers */ +#define MPFS_CANFD_RX_STATUS_RXE (1 << 0) +#define MPFS_CANFD_RX_STATUS_RXF (1 << 1) +#define MPFS_CANFD_RX_STATUS_RXMOF (1 << 2) +#define MPFS_CANFD_RX_STATUS_RXFRC_SHIFT (4) +#define MPFS_CANFD_RX_STATUS_RXFRC (0x07ff << MPFS_CANFD_RX_STATUS_RXFRC_SHIFT) +#define MPFS_CANFD_RX_STATUS_RTSOP (1 << 16) + +/* RX_DATA registers */ +#define MPFS_CANFD_RX_DATA_RX_DATA (0xffffffff << 0) + +/* TX_STATUS registers */ +#define MPFS_CANFD_TX_STATUS_TX1S_SHIFT (0) +#define MPFS_CANFD_TX_STATUS_TX1S (0x0f << MPFS_CANFD_TX_STATUS_TX1S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX2S_SHIFT (4) +#define MPFS_CANFD_TX_STATUS_TX2S (0x0f << MPFS_CANFD_TX_STATUS_TX2S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX3S_SHIFT (8) +#define MPFS_CANFD_TX_STATUS_TX3S (0x0f << MPFS_CANFD_TX_STATUS_TX3S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX4S_SHIFT (12) +#define MPFS_CANFD_TX_STATUS_TX4S (0x0f << MPFS_CANFD_TX_STATUS_TX4S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX5S_SHIFT (16) +#define MPFS_CANFD_TX_STATUS_TX5S (0x0f << MPFS_CANFD_TX_STATUS_TX5S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX6S_SHIFT (20) +#define MPFS_CANFD_TX_STATUS_TX6S (0x0f << MPFS_CANFD_TX_STATUS_TX6S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX7S_SHIFT (24) +#define MPFS_CANFD_TX_STATUS_TX7S (0x0f << MPFS_CANFD_TX_STATUS_TX7S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX8S_SHIFT (28) +#define MPFS_CANFD_TX_STATUS_TX8S (0x0f << MPFS_CANFD_TX_STATUS_TX8S_SHIFT) + +/* TX_COMMAND TXTB_INFO registers */ +#define MPFS_CANFD_TX_COMMAND_TXCE (1 << 0) +#define MPFS_CANFD_TX_COMMAND_TXCR (1 << 1) +#define MPFS_CANFD_TX_COMMAND_TXCA (1 << 2) +#define MPFS_CANFD_TX_COMMAND_TXB1 (1 << 8) +#define MPFS_CANFD_TX_COMMAND_TXB2 (1 << 9) +#define MPFS_CANFD_TX_COMMAND_TXB3 (1 << 10) +#define MPFS_CANFD_TX_COMMAND_TXB4 (1 << 11) +#define MPFS_CANFD_TX_COMMAND_TXB5 (1 << 12) +#define MPFS_CANFD_TX_COMMAND_TXB6 (1 << 13) +#define MPFS_CANFD_TX_COMMAND_TXB7 (1 << 14) +#define MPFS_CANFD_TX_COMMAND_TXB8 (1 << 15) +#define MPFS_CANFD_TX_COMMAND_TXT_BUFFER_COUNT_SHIFT (16) +#define MPFS_CANFD_TX_COMMAND_TXT_BUFFER_COUNT (0x0f << MPFS_CANFD_TX_COMMAND_TXT_BUFFER_COUNT_SHIFT) + +/* TX_PRIORITY registers */ +#define MPFS_CANFD_TX_PRIORITY_TXT1P_SHIFT (0) +#define MPFS_CANFD_TX_PRIORITY_TXT1P (0x07 << )MPFS_CANFD_TX_PRIORITY_TXT1P_SHIFT +#define MPFS_CANFD_TX_PRIORITY_TXT2P_SHIFT (4) +#define MPFS_CANFD_TX_PRIORITY_TXT2P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT2P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT3P_SHIFT (8) +#define MPFS_CANFD_TX_PRIORITY_TXT3P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT3P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT4P_SHIFT (12) +#define MPFS_CANFD_TX_PRIORITY_TXT4P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT4P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT5P_SHIFT (16) +#define MPFS_CANFD_TX_PRIORITY_TXT5P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT5P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT6P_SHIFT (20) +#define MPFS_CANFD_TX_PRIORITY_TXT6P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT6P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT7P_SHIFT (24) +#define MPFS_CANFD_TX_PRIORITY_TXT7P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT7P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT8P_SHIFT (28) +#define MPFS_CANFD_TX_PRIORITY_TXT8P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT8P_SHIFT) + +/* ERR_CAPT RETR_CTR ALC registers */ +#define MPFS_CANFD_ERR_CAPT_ERR_POS_SHIFT (0) +#define MPFS_CANFD_ERR_CAPT_ERR_POS (0x1f << MPFS_CANFD_ERR_CAPT_ERR_POS_SHIFT) +#define MPFS_CANFD_ERR_CAPT_ERR_TYPE_SHIFT (5) +#define MPFS_CANFD_ERR_CAPT_ERR_TYPE (0x07 << MPFS_CANFD_ERR_CAPT_ERR_TYPE_SHIFT) +#define MPFS_CANFD_ERR_CAPT_RETR_CTR_VAL_SHIFT (8) +#define MPFS_CANFD_ERR_CAPT_RETR_CTR_VAL (0x0f << MPFS_CANFD_ERR_CAPT_RETR_CTR_VAL_SHIFT) +#define MPFS_CANFD_ERR_CAPT_ALC_BIT_SHIFT (16) +#define MPFS_CANFD_ERR_CAPT_ALC_BIT (0x1f << MPFS_CANFD_ERR_CAPT_ALC_BIT_SHIFT) +#define MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD_SHIFT (21) +#define MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD (0x07 << MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD_SHIFT) + +/* TRV_DELAY SSP_CFG registers */ +#define MPFS_CANFD_TRV_DELAY_TRV_DELAY_VALUE_SHIFT (0) +#define MPFS_CANFD_TRV_DELAY_TRV_DELAY_VALUE (0x7f << MPFS_CANFD_TRV_DELAY_TRV_DELAY_VALUE_SHIFT) +#define MPFS_CANFD_TRV_DELAY_SSP_OFFSET_SHIFT (16) +#define MPFS_CANFD_TRV_DELAY_SSP_OFFSET (0xff << MPFS_CANFD_TRV_DELAY_SSP_OFFSET_SHIFT) +#define MPFS_CANFD_TRV_DELAY_SSP_SRC_SHIFT (24) +#define MPFS_CANFD_TRV_DELAY_SSP_SRC (0x03 << MPFS_CANFD_TRV_DELAY_SSP_SRC_SHIFT) + +/* RX_FR_CTR registers */ +#define MPFS_CANFD_RX_FR_CTR_RX_FR_CTR_VAL (0xffffffff << 0) + +/* TX_FR_CTR registers */ +#define MPFS_CANFD_TX_FR_CTR_TX_FR_CTR_VAL (0xffffffff << 0) + +/* DEBUG_REGISTER registers */ +#define MPFS_CANFD_DEBUG_REGISTER_STUFF_COUNT_SHIFT (0) +#define MPFS_CANFD_DEBUG_REGISTER_STUFF_COUNT (0x07 << MPFS_CANFD_DEBUG_REGISTER_STUFF_COUNT_SHIFT) +#define MPFS_CANFD_DEBUG_REGISTER_DESTUFF_COUNT_SHIFT (3) +#define MPFS_CANFD_DEBUG_REGISTER_DESTUFF_COUNT (0x07 << MPFS_CANFD_DEBUG_REGISTER_DESTUFF_COUNT_SHIFT) +#define MPFS_CANFD_DEBUG_REGISTER_PC_ARB (1 << 6) +#define MPFS_CANFD_DEBUG_REGISTER_PC_CON (1 << 7) +#define MPFS_CANFD_DEBUG_REGISTER_PC_DAT (1 << 8) +#define MPFS_CANFD_DEBUG_REGISTER_PC_STC (1 << 9) +#define MPFS_CANFD_DEBUG_REGISTER_PC_CRC (1 << 10) +#define MPFS_CANFD_DEBUG_REGISTER_PC_CRCD (1 << 11) +#define MPFS_CANFD_DEBUG_REGISTER_PC_ACK (1 << 12) +#define MPFS_CANFD_DEBUG_REGISTER_PC_ACKD (1 << 13) +#define MPFS_CANFD_DEBUG_REGISTER_PC_EOF (1 << 14) +#define MPFS_CANFD_DEBUG_REGISTER_PC_INT (1 << 15) +#define MPFS_CANFD_DEBUG_REGISTER_PC_SUSP (1 << 16) +#define MPFS_CANFD_DEBUG_REGISTER_PC_OVR (1 << 17) +#define MPFS_CANFD_DEBUG_REGISTER_PC_SOF (1 << 18) + +/* YOLO_REG registers */ +#define MPFS_CANFD_YOLO_REG_YOLO_VAL (0xffffffff << 0) + +/* TIMESTAMP_LOW registers */ +#define MPFS_CANFD_TIMESTAMP_LOW_TIMESTAMP_LOW (0xffffffff << 0) + +/* TIMESTAMP_HIGH registers */ +#define MPFS_CANFD_TIMESTAMP_HIGH_TIMESTAMP_HIGH (0xffffffff << 0) + +#endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_FPGA_CANFD_H */ \ No newline at end of file diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h b/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h index 5d93013734d19..54d9fda0c2d2c 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h @@ -130,4 +130,15 @@ #define MPFS_UART3_BASE MPFS_UART3_LO_BASE #define MPFS_UART4_BASE MPFS_UART4_LO_BASE +/* FPGA UART defines */ + +#define MPFS_FPGA_UART0_BASE 0x4c000000UL +#define MPFS_FPGA_UART1_BASE 0x4c001000UL +#define MPFS_FPGA_UART2_BASE 0x4c002000UL +#define MPFS_FPGA_UART3_BASE 0x4c003000UL +#define MPFS_FPGA_UART4_BASE 0x4c004000UL +#define MPFS_FPGA_UART5_BASE 0x4c005000UL +#define MPFS_FPGA_UART6_BASE 0x4c006000UL +#define MPFS_FPGA_UART7_BASE 0x4c007000UL + #endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_MEMORYMAP_H */ diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_mpucfg.h b/arch/risc-v/src/mpfs/hardware/mpfs_mpucfg.h index e7aaecdf798d7..6047dd8dbbba5 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_mpucfg.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_mpucfg.h @@ -21,6 +21,25 @@ #ifndef __ARCH_RISC_V_SRC_MPFS_HARDWARE_MPFS_MPUCFG_H #define __ARCH_RISC_V_SRC_MPFS_HARDWARE_MPFS_MPUCFG_H +/* FIC0 (FPGA) PMP configurations - for fabric memory transfers */ + +#define MPFS_PMPCFG_FIC0_0 (MPFS_MPUCFG_BASE + 0x00) +#define MPFS_PMPCFG_FIC0_1 (MPFS_MPUCFG_BASE + 0x08) +#define MPFS_PMPCFG_FIC0_2 (MPFS_MPUCFG_BASE + 0x10) +#define MPFS_PMPCFG_FIC0_3 (MPFS_MPUCFG_BASE + 0x18) +#define MPFS_PMPCFG_FIC0_4 (MPFS_MPUCFG_BASE + 0x20) +#define MPFS_PMPCFG_FIC0_5 (MPFS_MPUCFG_BASE + 0x28) +#define MPFS_PMPCFG_FIC0_6 (MPFS_MPUCFG_BASE + 0x30) +#define MPFS_PMPCFG_FIC0_7 (MPFS_MPUCFG_BASE + 0x38) +#define MPFS_PMPCFG_FIC0_8 (MPFS_MPUCFG_BASE + 0x40) +#define MPFS_PMPCFG_FIC0_9 (MPFS_MPUCFG_BASE + 0x48) +#define MPFS_PMPCFG_FIC0_10 (MPFS_MPUCFG_BASE + 0x50) +#define MPFS_PMPCFG_FIC0_11 (MPFS_MPUCFG_BASE + 0x58) +#define MPFS_PMPCFG_FIC0_12 (MPFS_MPUCFG_BASE + 0x60) +#define MPFS_PMPCFG_FIC0_13 (MPFS_MPUCFG_BASE + 0x68) +#define MPFS_PMPCFG_FIC0_14 (MPFS_MPUCFG_BASE + 0x70) +#define MPFS_PMPCFG_FIC0_15 (MPFS_MPUCFG_BASE + 0x78) + /* FIC1 (FPGA) PMP configurations - for fabric memory transfers */ #define MPFS_PMPCFG_FIC1_0 (MPFS_MPUCFG_BASE + 0x100) @@ -40,6 +59,17 @@ #define MPFS_PMPCFG_FIC1_14 (MPFS_MPUCFG_BASE + 0x170) #define MPFS_PMPCFG_FIC1_15 (MPFS_MPUCFG_BASE + 0x178) +/* FIC2 (FPGA) PMP configurations - for fabric memory transfers */ + +#define MPFS_PMPCFG_FIC2_0 (MPFS_MPUCFG_BASE + 0x200) +#define MPFS_PMPCFG_FIC2_1 (MPFS_MPUCFG_BASE + 0x208) +#define MPFS_PMPCFG_FIC2_2 (MPFS_MPUCFG_BASE + 0x210) +#define MPFS_PMPCFG_FIC2_3 (MPFS_MPUCFG_BASE + 0x218) +#define MPFS_PMPCFG_FIC2_4 (MPFS_MPUCFG_BASE + 0x220) +#define MPFS_PMPCFG_FIC2_5 (MPFS_MPUCFG_BASE + 0x228) +#define MPFS_PMPCFG_FIC2_6 (MPFS_MPUCFG_BASE + 0x230) +#define MPFS_PMPCFG_FIC2_7 (MPFS_MPUCFG_BASE + 0x238) + /* Crpyto PMP configurations - for DMA transfers */ #define MPFS_PMPCFG_CRYPTO_0 (MPFS_MPUCFG_BASE + 0x300) @@ -53,10 +83,18 @@ #define MPFS_PMPCFG_ETH0_1 (MPFS_MPUCFG_BASE + 0x408) #define MPFS_PMPCFG_ETH0_2 (MPFS_MPUCFG_BASE + 0x410) #define MPFS_PMPCFG_ETH0_3 (MPFS_MPUCFG_BASE + 0x418) +#define MPFS_PMPCFG_ETH0_4 (MPFS_MPUCFG_BASE + 0x420) +#define MPFS_PMPCFG_ETH0_5 (MPFS_MPUCFG_BASE + 0x428) +#define MPFS_PMPCFG_ETH0_6 (MPFS_MPUCFG_BASE + 0x430) +#define MPFS_PMPCFG_ETH0_7 (MPFS_MPUCFG_BASE + 0x438) #define MPFS_PMPCFG_ETH1_0 (MPFS_MPUCFG_BASE + 0x500) #define MPFS_PMPCFG_ETH1_1 (MPFS_MPUCFG_BASE + 0x508) #define MPFS_PMPCFG_ETH1_2 (MPFS_MPUCFG_BASE + 0x510) #define MPFS_PMPCFG_ETH1_3 (MPFS_MPUCFG_BASE + 0x518) +#define MPFS_PMPCFG_ETH1_4 (MPFS_MPUCFG_BASE + 0x520) +#define MPFS_PMPCFG_ETH1_5 (MPFS_MPUCFG_BASE + 0x528) +#define MPFS_PMPCFG_ETH1_6 (MPFS_MPUCFG_BASE + 0x530) +#define MPFS_PMPCFG_ETH1_7 (MPFS_MPUCFG_BASE + 0x528) /* USB PMP configurations - for DMA transfers */ @@ -72,6 +110,22 @@ #define MPFS_PMPCFG_MMC_2 (MPFS_MPUCFG_BASE + 0x710) #define MPFS_PMPCFG_MMC_3 (MPFS_MPUCFG_BASE + 0x718) +/* SCB PMP configurations - for DMA transfers */ + +#define MPFS_PMPCFG_SCB_0 (MPFS_MPUCFG_BASE + 0x800) +#define MPFS_PMPCFG_SCB_1 (MPFS_MPUCFG_BASE + 0x808) +#define MPFS_PMPCFG_SCB_2 (MPFS_MPUCFG_BASE + 0x810) +#define MPFS_PMPCFG_SCB_3 (MPFS_MPUCFG_BASE + 0x818) +#define MPFS_PMPCFG_SCB_4 (MPFS_MPUCFG_BASE + 0x820) +#define MPFS_PMPCFG_SCB_5 (MPFS_MPUCFG_BASE + 0x828) +#define MPFS_PMPCFG_SCB_6 (MPFS_MPUCFG_BASE + 0x830) +#define MPFS_PMPCFG_SCB_7 (MPFS_MPUCFG_BASE + 0x838) + +/* TRACE PMP configurations - for DMA transfers */ + +#define MPFS_PMPCFG_TRACE_0 (MPFS_MPUCFG_BASE + 0x900) +#define MPFS_PMPCFG_TRACE_1 (MPFS_MPUCFG_BASE + 0x908) + /* DDR segments - set up by mpfs_ddr.c */ #define MPFS_MPUCFG_SEG0_REG0 (MPFS_MPUCFG_BASE + 0xd00) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_usb.h b/arch/risc-v/src/mpfs/hardware/mpfs_usb.h index 863044d8ddd9a..00f15dbedaf79 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_usb.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_usb.h @@ -142,6 +142,8 @@ #define MPFS_USB_C_T_HHSRTN_OFFSET 0x346 #define MPFS_USB_C_T_HSBT_OFFSET 0x348 +#define MPFS_USB_DMA_ADDR_UPPER_REG_OFFSET 0x3FC + #define MPFS_USB_POWER (MPFS_USB_BASE + MPFS_USB_POWER_OFFSET) #define MPFS_USB_POWER_ENABLE_SUSPENDM (1 << 0) #define MPFS_USB_POWER_SUSPEND_MODE (1 << 1) @@ -175,6 +177,12 @@ #define MPFS_USB_RX_DPBUF_DIS (MPFS_USB_BASE + MPFS_USB_RX_DPBUF_DIS_OFFSET) #define MPFS_USB_TX_DPBUF_DIS (MPFS_USB_BASE + MPFS_USB_TX_DPBUF_DIS_OFFSET) +/* MPFS_USB_DMA_ADDR_UPPER_REG is used to set the upper 6-bits of + * the Address bus for USB DMA operations. + */ + +#define MPFS_USB_DMA_ADDR_UPPER_REG (MPFS_USB_BASE + MPFS_USB_DMA_ADDR_UPPER_REG_OFFSET) + #define MPFS_USB_DMA_CHANNEL(n) (MPFS_USB_BASE + MPFS_USB_DMA_CHANNEL_OFFSET + MPFS_USB_DMA_CHANNEL_SIZE * n) /**************************************************************************** @@ -419,6 +427,7 @@ struct mpfs_ep_s struct mpfs_rqhead_s reqq; /* Read/write request queue */ struct mpfs_rqhead_s pendq; /* Write requests pending stall sent */ struct usbdev_epdesc_s *descb[2]; /* Pointers to this endpoint descriptors */ + uint32_t linkdead; /* Remote end has closed the connection */ volatile uint8_t epstate; /* State of the endpoint (see enum mpfs_epstate_e) */ uint8_t stalled:1; /* true: Endpoint is stalled */ uint8_t pending:1; /* true: IN Endpoint stall is pending */ diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_wdog.h b/arch/risc-v/src/mpfs/hardware/mpfs_wdog.h new file mode 100644 index 0000000000000..a2059e1f41958 --- /dev/null +++ b/arch/risc-v/src/mpfs/hardware/mpfs_wdog.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/hardware/mpfs_wdog.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_WDOG_H +#define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_WDOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Magic value for REFRESH register to reload watchdog countdown counter */ + +#define WDOG_REFRESH_RELOAD (0xdeadc0de) + +/* Magic value for FORCE register to perform immediate system reset */ + +#define WDOG_FORCE_IMMEDIATE_RESET (0x0c) + +/**************************************************************************** + * Register Offsets + ****************************************************************************/ + +#define MPFS_WDOG_REFRESH_OFFSET 0x000 /* Write value 0xdeadc0de to reset wdog. Read to get current count value */ +#define MPFS_WDOG_CONTROL_OFFSET 0x004 /* WDOG counter register */ +#define MPFS_WDOG_STATUS_OFFSET 0x008 /* WDOG status register */ +#define MPFS_WDOG_TIME_OFFSET 0x00C /* Set WDOG time value */ +#define MPFS_WDOG_MSVP_OFFSET 0x010 /* Set MSVP int level */ +#define MPFS_WDOG_TRIGGER_OFFSET 0x014 /* Set NMI int level */ +#define MPFS_WDOG_FORCE_OFFSET 0x018 /* Force trigger WDOG NMI seq. Writing 0xc triggers immediate reset */ + +/**************************************************************************** + * Control register masks + ****************************************************************************/ + +#define WDOG_CONTROL_INTEN_MSVP_MASK (1 << 0) /* Bit 0: Enable MVRP interrupt when MVRP level is passed */ +#define WDOG_CONTROL_INTEN_TRIG_MASK (1 << 1) /* Bit 1: Enable NMI interrupt. This bit is permanenty set */ +#define WDOG_CONTROL_INTEN_SLEEP_MASK (1 << 2) /* Bit 2: Enable MVRP interrupt when MVRP level is passed and M3 is sleeping */ +#define WDOG_CONTROL_ACTIVE_SLEEP_MASK (1 << 3) /* Bit 3: Set WDOG operational during CPU sleep */ +#define WDOG_CONTROL_ENABLE_FORBITTEN_MASK (1 << 4) /* Bit 4: Enable trigger wdog from write during forbitten window */ + +/**************************************************************************** + * Status register masks + ****************************************************************************/ + +#define WDOG_STATUS_MVRP_TRIPPED_MASK (1 << 0) /* Bit 0: MVRP level has passed. Write to clear interrupt */ +#define WDOG_STATUS_WDOG_TRIPPED_MASK (1 << 1) /* Bit 1: TRIGGER level has passed and NMI is asserted. Write to clear interrupt */ +#define WDOG_STATUS_FORBITTEN_MASK (1 << 2) /* Bit 2: Watchdog in forbitten window */ +#define WDOG_STATUS_TRIGGERED_MASK (1 << 3) /* Bit 3: Watchdog has triggered */ +#define WDOG_STATUS_LOCKED_MASK (1 << 4) /* Bit 4: Following registers are locked and cannot be changed */ +#define WDOG_STATUS_DEVRST_MASK (1 << 5) /* Bit 5: DEVRST caused NMI */ + +#endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_WDOG_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_clockconfig.c b/arch/risc-v/src/mpfs/mpfs_clockconfig.c index 320021a27805f..7802560cfa838 100644 --- a/arch/risc-v/src/mpfs/mpfs_clockconfig.c +++ b/arch/risc-v/src/mpfs/mpfs_clockconfig.c @@ -143,6 +143,8 @@ enum part_type_e static uint64_t g_cpu_clock = MPFS_MSS_EXT_SGMII_REF_CLK; +#ifdef CONFIG_MPFS_BOOTLOADER + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -630,6 +632,8 @@ void mpfs_clockconfig(void) mpfs_pll_config(); } +#endif + /**************************************************************************** * Name: mpfs_get_cpuclk ****************************************************************************/ diff --git a/arch/risc-v/src/mpfs/mpfs_config.h b/arch/risc-v/src/mpfs/mpfs_config.h index ce2007d599822..896036b5c6ac9 100644 --- a/arch/risc-v/src/mpfs/mpfs_config.h +++ b/arch/risc-v/src/mpfs/mpfs_config.h @@ -37,7 +37,8 @@ #undef HAVE_UART_DEVICE #if defined(CONFIG_MPFS_UART0) || defined(CONFIG_MPFS_UART1) || \ defined(CONFIG_MPFS_UART2) || defined(CONFIG_MPFS_UART3) || \ - defined(CONFIG_MPFS_UART4) + defined(CONFIG_MPFS_UART4) || defined(CONFIG_MPFS_UART5) || \ + defined(CONFIG_MPFS_UART6) || defined(CONFIG_MPFS_UART7) # define HAVE_UART_DEVICE 1 #endif @@ -46,30 +47,72 @@ # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #elif defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART1) # undef CONFIG_UART0_SERIAL_CONSOLE # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART2) # undef CONFIG_UART0_SERIAL_CONSOLE # undef CONFIG_UART1_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART3) # undef CONFIG_UART0_SERIAL_CONSOLE # undef CONFIG_UART1_SERIAL_CONSOLE # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART4) # undef CONFIG_UART0_SERIAL_CONSOLE # undef CONFIG_UART1_SERIAL_CONSOLE # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART5_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART5) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART6_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART6) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART7_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART7) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #else # undef CONFIG_UART0_SERIAL_CONSOLE diff --git a/arch/risc-v/src/mpfs/mpfs_coremmc.c b/arch/risc-v/src/mpfs/mpfs_coremmc.c index 02d8bd7499ad6..b725f1556cef6 100644 --- a/arch/risc-v/src/mpfs/mpfs_coremmc.c +++ b/arch/risc-v/src/mpfs/mpfs_coremmc.c @@ -45,10 +45,12 @@ #include -#include "mpfs_emmcsd.h" +#include "mpfs_coremmc.h" #include "riscv_internal.h" #include "hardware/mpfs_coremmc.h" +#include "mpfs_sdio_dev.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -158,54 +160,6 @@ * Private Types ****************************************************************************/ -/* This structure defines the state of the MPFS eMMCSD interface */ - -struct mpfs_dev_s -{ - struct sdio_dev_s dev; /* Standard, base SDIO interface */ - - const uintptr_t hw_base; /* Base address */ - const int plic_irq; /* PLIC interrupt */ - bool clk_enabled; /* Clk state */ - - /* Event support */ - - sem_t waitsem; /* Implements event waiting */ - sdio_eventset_t waitevents; /* Set of events to be waited for */ - uint32_t waitmask; /* Interrupt enables for event waiting */ - volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */ - struct wdog_s waitwdog; /* Watchdog that handles event timeouts */ - - /* Callback support */ - - sdio_statset_t cdstatus; /* Card status */ - sdio_eventset_t cbevents; /* Set of events to be cause callbacks */ - worker_t callback; /* Registered callback function */ - void *cbarg; /* Registered callback argument */ - struct work_s cbwork; /* Callback work queue structure */ - - /* Interrupt mode data transfer support */ - - uint32_t *buffer; /* Address of current R/W buffer */ - size_t remaining; /* Number of bytes remaining in the transfer */ - size_t receivecnt; /* Real count to receive */ - uint32_t xfrmask; /* Interrupt enables for data transfer */ - uint32_t xfr_blkmask; /* Interrupt enables for SB/MB data transfer */ - - bool widebus; /* Required for DMA support */ - bool onebit; /* true: Only 1-bit transfers are supported */ - - /* Data transfer support */ - - bool polltransfer; /* Indicate a poll transfer, no DMA */ - bool multiblock; /* Indicate a multi-block transfer */ - - /* Misc */ - - uint32_t blocksize; /* Current block size */ - uint32_t fifo_depth; /* Fifo size, read from the register */ -}; - union { uint32_t w; @@ -2277,7 +2231,7 @@ static void mpfs_callback(void *arg) ****************************************************************************/ /**************************************************************************** - * Name: sdio_initialize + * Name: mpfs_coremmc_sdio_initialize * * Description: * Initialize SDIO for operation. @@ -2291,7 +2245,7 @@ static void mpfs_callback(void *arg) * ****************************************************************************/ -struct sdio_dev_s *sdio_initialize(int slotno) +struct sdio_dev_s *mpfs_coremmc_sdio_initialize(int slotno) { struct mpfs_dev_s *priv = &g_coremmc_dev; @@ -2308,7 +2262,7 @@ struct sdio_dev_s *sdio_initialize(int slotno) } /**************************************************************************** - * Name: sdio_mediachange + * Name: mpfs_coremmc_sdio_mediachange * * Description: * Called by board-specific logic -- possible from an interrupt handler -- @@ -2326,7 +2280,7 @@ struct sdio_dev_s *sdio_initialize(int slotno) * ****************************************************************************/ -void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) +void mpfs_coremmc_sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) { struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev; sdio_statset_t cdstatus; @@ -2359,7 +2313,7 @@ void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) } /**************************************************************************** - * Name: sdio_wrprotect + * Name: mpfs_coremmc_sdio_wrprotect * * Description: * Called by board-specific logic to report if the card in the slot is @@ -2374,7 +2328,7 @@ void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) * ****************************************************************************/ -void sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect) +void mpfs_coremmc_sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect) { struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev; irqstate_t flags; diff --git a/arch/risc-v/src/mpfs/mpfs_coremmc.h b/arch/risc-v/src/mpfs/mpfs_coremmc.h index 86cc90dca2ff3..95bf79b4d3b9b 100644 --- a/arch/risc-v/src/mpfs/mpfs_coremmc.h +++ b/arch/risc-v/src/mpfs/mpfs_coremmc.h @@ -48,7 +48,7 @@ extern "C" #endif /**************************************************************************** - * Name: sdio_initialize + * Name: mpfs_coremmc_sdio_initialize * * Description: * Initialize SDIO for operation. @@ -63,10 +63,10 @@ extern "C" ****************************************************************************/ struct sdio_dev_s; /* See include/nuttx/sdio.h */ -struct sdio_dev_s *sdio_initialize(int slotno); +struct sdio_dev_s *mpfs_coremmc_sdio_initialize(int slotno); /**************************************************************************** - * Name: sdio_mediachange + * Name: mpfs_coremmc_sdio_mediachange * * Description: * Called by board-specific logic -- possibly from an interrupt handler -- @@ -84,10 +84,10 @@ struct sdio_dev_s *sdio_initialize(int slotno); * ****************************************************************************/ -void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot); +void mpfs_coremmc_sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot); /**************************************************************************** - * Name: sdio_wrprotect + * Name: mpfs_coremmc_sdio_wrprotect * * Description: * Called by board-specific logic to report if the card in the slot is @@ -102,7 +102,7 @@ void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot); * ****************************************************************************/ -void sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect); +void mpfs_coremmc_sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect); #undef EXTERN #if defined(__cplusplus) diff --git a/arch/risc-v/src/mpfs/mpfs_corepwm.c b/arch/risc-v/src/mpfs/mpfs_corepwm.c index e291bc6ab5a1d..b59d3250b6172 100644 --- a/arch/risc-v/src/mpfs/mpfs_corepwm.c +++ b/arch/risc-v/src/mpfs/mpfs_corepwm.c @@ -76,7 +76,6 @@ struct mpfs_pwmtimer_s struct mpfs_pwmchan_s channels[MPFS_MAX_PWM_CHANNELS]; uint32_t frequency; /* Current frequency setting */ uintptr_t base; /* The base address of the pwm block */ - uint32_t pwmclk; /* The frequency of the pwm clock */ }; /**************************************************************************** @@ -187,7 +186,6 @@ static struct mpfs_pwmtimer_s g_pwm0dev = } }, .base = CONFIG_MPFS_COREPWM0_BASE, - .pwmclk = CONFIG_MPFS_COREPWM0_PWMCLK, }; #endif @@ -249,7 +247,6 @@ static struct mpfs_pwmtimer_s g_pwm1dev = } }, .base = CONFIG_MPFS_COREPWM1_BASE, - .pwmclk = CONFIG_MPFS_COREPWM1_PWMCLK, }; #endif @@ -404,12 +401,12 @@ static int pwm_timer(struct mpfs_pwmtimer_s *priv, * PERIOD = pwmclk / frequency = 25,000,000 / 50 = 500,000 */ - pwminfo("PWM%u frequency: %u PWMCLK: %u prescaler: %u\n", - priv->pwmid, info->frequency, priv->pwmclk, prescaler); + pwminfo("PWM%u frequency: %u PWMCLK: %lu prescaler: %u\n", + priv->pwmid, info->frequency, MPFS_FPGA_PERIPHERAL_CLK, prescaler); /* Set the reload and prescaler values */ - period = priv->pwmclk / info->frequency; + period = MPFS_FPGA_PERIPHERAL_CLK / info->frequency; pwm_putreg(priv, MPFS_COREPWM_PERIOD_OFFSET, period); pwm_putreg(priv, MPFS_COREPWM_PRESCALE_OFFSET, prescaler); diff --git a/arch/risc-v/src/mpfs/mpfs_corespi.c b/arch/risc-v/src/mpfs/mpfs_corespi.c index f92ed0123c8e1..e4931f86f7508 100644 --- a/arch/risc-v/src/mpfs/mpfs_corespi.c +++ b/arch/risc-v/src/mpfs/mpfs_corespi.c @@ -1435,6 +1435,22 @@ static void mpfs_spi_init(struct spi_dev_s *dev) mpfs_spi_set_master_mode(priv, 1); mpfs_spi_enable(priv, 1); + /* Disable all interrupt sources */ + + modifyreg32(MPFS_SPI_CONTROL, MPFS_SPI_INTTXTURUN | + MPFS_SPI_INTRXOVRFLOW | + MPFS_SPI_INTTXDONE, + 0); + + /* Clear all interrupt sources */ + + putreg32(MPFS_SPI_TXCHUNDRUN | + MPFS_SPI_RXCHOVRFLW | + MPFS_SPI_DATA_RX | + MPFS_SPI_TXDONE, MPFS_SPI_INT_CLEAR); + + /* Then enable the interrupt */ + up_enable_irq(priv->plic_irq); } diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index 3819fba3a91f5..565770dc1fed7 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -100,8 +100,6 @@ /* Retraining limits */ -#define ABNORMAL_RETRAIN_CA_DECREASE_COUNT 2 -#define ABNORMAL_RETRAIN_CA_DLY_DECREASE_COUNT 2 #define DQ_DQS_NUM_TAPS 5 /* PLL convenience bits */ @@ -719,6 +717,8 @@ static int mpfs_ddr_pll_lock_scb(void) #define INIT_SETTING_SEG1_6 0x00000000 #define INIT_SETTING_SEG1_7 0x00000000 +#define SEG_LOCKED (1 << 31) + /**************************************************************************** * Name: mpfs_setup_ddr_segments * @@ -758,11 +758,18 @@ void mpfs_setup_ddr_segments(enum seg_setup_e option) } else { + /* This is the final configuration that cannot be changed after being + * locked. + */ + /* Segment 0 */ val_l = LIBERO_SETTING_SEG0_0 & 0x7fff; val_h = LIBERO_SETTING_SEG0_1 & 0x7fff; + val_l |= SEG_LOCKED; + val_h |= SEG_LOCKED; + putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG0_REG0); /* Segment 1 */ @@ -770,18 +777,24 @@ void mpfs_setup_ddr_segments(enum seg_setup_e option) val_l = LIBERO_SETTING_SEG1_2 & 0x7fff; val_h = LIBERO_SETTING_SEG1_3 & 0x7fff; + val_l |= SEG_LOCKED; + val_h |= SEG_LOCKED; + putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG1_REG1); val_l = LIBERO_SETTING_SEG1_4 & 0x7fff; val_h = LIBERO_SETTING_SEG1_5 & 0x7fff; + val_l |= SEG_LOCKED; + val_h |= SEG_LOCKED; + putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG1_REG2); } /* Disable ddr blocker: cleared at reset. When written to '1' disables * the blocker function allowing the L2 cache controller to access the * DDRC. Once written to '1' the register cannot be written to 0, only - * an devie reset will clear the register. + * an device reset will clear the register. */ putreg64((((uint64_t)0x01) << 32) , MPFS_MPUCFG_SEG0_REG3); @@ -3407,15 +3420,15 @@ static int mpfs_training_addcmd(void) static int mpfs_training_verify(void) { - uint32_t low_ca_dly_count; - uint32_t decrease_count; uint32_t addcmd_status0; uint32_t addcmd_status1; uint32_t retries = MPFS_DEFAULT_RETRIES; uint32_t t_status = 0; uint32_t lane_sel; - uint32_t last; uint32_t i; + uint32_t off_taps; + uint32_t width_taps; + uint32_t gt_clk_sel; while (!(getreg32(MPFS_DDR_CSR_APB_STAT_DFI_TRAINING_COMPLETE) & 0x01) && --retries); @@ -3426,19 +3439,15 @@ static int mpfs_training_verify(void) return -ETIMEDOUT; } - for (lane_sel = 0; lane_sel < LIBERO_SETTING_DATA_LANES_USED; lane_sel++) - { - mpfs_wait_cycles(10); - - putreg32(lane_sel, MPFS_CFG_DDR_SGMII_PHY_LANE_SELECT); - mpfs_wait_cycles(10); - - /* Verify cmd address results, rejects if not acceptable */ + /* Verify cmd address results, rejects if not acceptable */ - addcmd_status0 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS0); - addcmd_status1 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS1); + addcmd_status0 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS0); + addcmd_status1 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS1); - uint32_t ca_status[8] = + if ((LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) != ADDCMD_BIT) + { + unsigned low_ca_dly_count = 0; + uint8_t ca_status[8] = { ((addcmd_status0) & 0xff), ((addcmd_status0 >> 8) & 0xff), @@ -3450,46 +3459,40 @@ static int mpfs_training_verify(void) ((addcmd_status1 >> 24) & 0xff) }; - low_ca_dly_count = 0; - last = 0; - decrease_count = 0; + uint8_t last = ca_status[7]; + + /* Retrain if abnormal CA training result detected + * Expected result is increasing numbers, starting at index n and + * wrapping around. For example: + * [0x35, 0x3b, 0x4, 0x14, 0x1b, 0x21, 0x28, 0x2f]. + * + * Also they need to be separated by at least 5 + */ for (i = 0; i < 8; i++) { - if (ca_status[i] < 5) + if (ca_status[i] < last + 5) { low_ca_dly_count++; } - if (ca_status[i] <= last) - { - decrease_count++; - } - last = ca_status[i]; } - if (ca_status[0] <= ca_status[7]) - { - decrease_count++; - } - - if ((LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) != ADDCMD_BIT) + if (low_ca_dly_count > 1) { - /* Retrain if abnormal CA training result detected */ + /* Retrain via reset */ - if (low_ca_dly_count > ABNORMAL_RETRAIN_CA_DLY_DECREASE_COUNT) - { - t_status |= 0x01; - } + return -EIO; + } + } - /* Retrain if abnormal CA training result detected */ + for (lane_sel = 0; lane_sel < LIBERO_SETTING_DATA_LANES_USED; lane_sel++) + { + mpfs_wait_cycles(10); - if (decrease_count > ABNORMAL_RETRAIN_CA_DECREASE_COUNT) - { - t_status |= 0x01; - } - } + putreg32(lane_sel, MPFS_CFG_DDR_SGMII_PHY_LANE_SELECT); + mpfs_wait_cycles(10); /* Check that gate training passed without error */ @@ -3503,56 +3506,27 @@ static int mpfs_training_verify(void) t_status |= 0x01; } - /* Check that DQ/DQS calculated window is above 5 taps. */ + /* Check that DQ/DQS calculated window is above 5 taps + * and centered with margin + */ + + off_taps = getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS1); + width_taps = getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS2); - if (getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS2) < DQ_DQS_NUM_TAPS) + if (width_taps < DQ_DQS_NUM_TAPS || + width_taps + off_taps <= 16 + DQ_DQS_NUM_TAPS / 2) { t_status |= 0x01; } /* Extra checks */ - uint32_t temp = 0; - uint32_t gt_clk_sel = getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_CLK_SEL) & - 0x03; - - if ((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) & 0xff) == 0) - { - temp++; - if (gt_clk_sel == 0) - { - t_status |= 0x01; - } - } - - if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 8) & 0xff) == 0) - { - temp++; - if (gt_clk_sel == 1) - { - t_status |= 0x01; - } - } - - if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 16) & 0xff) == 0) - { - temp++; - if (gt_clk_sel == 2) - { - t_status |= 0x01; - } - } + /* Check the GT_TXDLY result for the selected clock */ - if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 24) & 0xff) == 0) - { - temp++; - if (gt_clk_sel == 3) - { - t_status |= 0x01; - } - } + gt_clk_sel = getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_CLK_SEL) & 0x03; - if (temp > 1) + if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> (gt_clk_sel * 8)) & + 0xff) == 0) { t_status |= 0x01; } diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c index 267894dc81c1e..37b1cc8075115 100644 --- a/arch/risc-v/src/mpfs/mpfs_emmcsd.c +++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c @@ -50,6 +50,8 @@ #include "hardware/mpfs_emmcsd.h" #include "hardware/mpfs_mpucfg.h" +#include "mpfs_sdio_dev.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -152,7 +154,7 @@ /* Provide default SD-card 4bit clk if unset at board.h */ #ifndef MPFS_SD_CLOCK_4BIT -# define MPFS_SD_CLOCK_4BIT MPFS_MMC_CLOCK_25MHZ +# define MPFS_SD_CLOCK_4BIT MPFS_MMC_CLOCK_50MHZ #endif /* Define the Hardware FIFO size */ @@ -291,58 +293,6 @@ * Private Types ****************************************************************************/ -/* This structure defines the state of the MPFS eMMCSD interface */ - -struct mpfs_dev_s -{ - struct sdio_dev_s dev; /* Standard, base SDIO interface */ - - const uintptr_t hw_base; /* Base address */ - const int plic_irq; /* PLIC interrupt */ - bool clk_enabled; /* Clk state */ - - /* eMMC / SD and HW parameters */ - - const bool emmc; /* eMMC or SD */ - int bus_voltage; /* Bus voltage */ - int bus_mode; /* eMMC Bus mode */ - bool jumpers_3v3; /* Jumper settings: 1v8 or 3v3 */ - - /* Event support */ - - sem_t waitsem; /* Implements event waiting */ - sdio_eventset_t waitevents; /* Set of events to be waited for */ - uint32_t waitmask; /* Interrupt enables for event waiting */ - volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */ - struct wdog_s waitwdog; /* Watchdog that handles event timeouts */ - - /* Callback support */ - - sdio_statset_t cdstatus; /* Card status */ - sdio_eventset_t cbevents; /* Set of events to be cause callbacks */ - worker_t callback; /* Registered callback function */ - void *cbarg; /* Registered callback argument */ - struct work_s cbwork; /* Callback work queue structure */ - - /* Interrupt mode data transfer support */ - - uint32_t *buffer; /* Address of current R/W buffer */ - size_t remaining; /* Number of bytes remaining in the transfer */ - size_t receivecnt; /* Real count to receive */ - uint32_t xfrmask; /* Interrupt enables for data transfer */ - - bool widebus; /* Required for DMA support */ - bool onebit; /* true: Only 1-bit transfers are supported */ - - /* DMA data transfer support */ - - bool polltransfer; /* Indicate a poll transfer, no DMA */ - - /* Misc */ - - uint32_t blocksize; /* Current block size */ -}; - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -779,12 +729,22 @@ static void mpfs_sendfifo(struct mpfs_dev_s *priv) * come back when we're good to write again. */ - if (priv->remaining && (!(getreg32(MPFS_EMMCSD_SRS09) & - MPFS_EMMCSD_SRS09_BWE))) + if (priv->remaining) { - modifyreg32(MPFS_EMMCSD_SRS14, 0, MPFS_EMMCSD_SRS14_BWR_IE); + /* Enable BWR before checking BWE bit */ + putreg32(MPFS_EMMCSD_SRS12_BWR, MPFS_EMMCSD_SRS12); - return; + modifyreg32(MPFS_EMMCSD_SRS14, 0, MPFS_EMMCSD_SRS14_BWR_IE); + if (!(getreg32(MPFS_EMMCSD_SRS09) & MPFS_EMMCSD_SRS09_BWE)) + { + return; + } + + /* There is still room for writing to buffer, + * disable BWR and continue. + */ + + modifyreg32(MPFS_EMMCSD_SRS14, MPFS_EMMCSD_SRS14_BWR_IE, 0); } } @@ -1135,14 +1095,14 @@ static int mpfs_emmcsd_interrupt(int irq, void *context, void *arg) { mcinfo("Card inserted!\n"); - sdio_mediachange((struct sdio_dev_s *)priv, true); + mpfs_emmcsd_sdio_mediachange((struct sdio_dev_s *)priv, true); putreg32(MPFS_EMMCSD_SRS12_CIN, MPFS_EMMCSD_SRS12); } else if (status & MPFS_EMMCSD_SRS12_CR) { mcinfo("Card removed!\n"); - sdio_mediachange((struct sdio_dev_s *)priv, false); + mpfs_emmcsd_sdio_mediachange((struct sdio_dev_s *)priv, false); putreg32(MPFS_EMMCSD_SRS12_CR, MPFS_EMMCSD_SRS12); } else @@ -1802,6 +1762,84 @@ static void mpfs_widebus(struct sdio_dev_s *dev, bool wide) } } +/**************************************************************************** + * Name: mpfs_clock + * + ****************************************************************************/ + +static void mpfs_set_hs_8bit(struct sdio_dev_s *dev) +{ + struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev; + int ret; + uint32_t r1; + uint32_t rr; + + /* mpfs to DDR mode */ + + modifyreg32(MPFS_EMMCSD_HRS06, 0x7, MPFS_EMMCSD_MODE_DDR); + + /* eMMC to HS mode */ + + if ((ret = mpfs_sendcmd(dev, MMCSD_CMD6, 0x03b90100u)) == OK) + { + if ((ret == mpfs_waitresponse(dev, MMCSD_CMD6)) == OK) + { + ret = mpfs_recvshortcrc(dev, MMCSD_CMD6, &r1); + } + } + + if (ret < 0) + { + mcerr("Failed to set high speed mode\n"); + goto err; + } + + /* While busy */ + + do + { + rr = getreg32(MPFS_EMMCSD_SRS09); + } + while ((rr & (1 << 20)) == 0); + + /* mpfs to 8-bit mode */ + + modifyreg32(MPFS_EMMCSD_SRS10, 0, MPFS_EMMCSD_SRS10_EDTW); + + /* eMMC to 8-bit DDR mode */ + + if ((ret = mpfs_sendcmd(dev, MMCSD_CMD6, 0x03b70600u)) == OK) + { + if ((ret == mpfs_waitresponse(dev, MMCSD_CMD6)) == OK) + { + ret = mpfs_recvshortcrc(dev, MMCSD_CMD6, &r1); + } + } + + if (ret < 0) + { + mcerr("Failed to set 8-bit mode\n"); + goto err; + } + + /* While busy */ + + do + { + rr = getreg32(MPFS_EMMCSD_SRS09); + } + while ((rr & (1 << 20)) == 0); + + return; + +err: + + /* Reset to 1-bit legacy mode */ + + modifyreg32(MPFS_EMMCSD_HRS06, 0, MPFS_EMMCSD_MODE_LEGACY); + modifyreg32(MPFS_EMMCSD_SRS10, MPFS_EMMCSD_SRS10_EDTW, 0); +} + /**************************************************************************** * Name: mpfs_clock * @@ -1845,7 +1883,8 @@ static void mpfs_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate) { clckr = MPFS_MMC_CLOCK_200MHZ; } - else if (priv->bus_mode == MPFS_EMMCSD_MODE_SDR) + else if (priv->bus_mode == MPFS_EMMCSD_MODE_SDR || + priv->bus_mode == MPFS_EMMCSD_MODE_DDR) { clckr = MPFS_MMC_CLOCK_50MHZ; } @@ -1866,10 +1905,17 @@ static void mpfs_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate) /* SD normal operation clocking (narrow 1-bit mode) */ case CLOCK_SD_TRANSFER_1BIT: - clckr = MPFS_MMC_CLOCK_25MHZ; + clckr = MPFS_MMC_CLOCK_50MHZ; break; } + if (rate == CLOCK_MMC_TRANSFER) + { + /* eMMC: Set 8-bit data bus and correct bus mode */ + + mpfs_set_hs_8bit(dev); + } + /* Set the new clock frequency */ mpfs_setclkrate(priv, clckr); @@ -2205,7 +2251,11 @@ static int mpfs_dmarecvsetup(struct sdio_dev_s *dev, mcinfo("Receive: %zu bytes\n", buflen); DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); - DEBUGASSERT(((uintptr_t)buffer & 3) == 0); + if (((uintptr_t)buffer & 3) != 0) + { + mcerr("Unaligned buffer: %p\n", buffer); + return -EFAULT; + } priv->buffer = (uint32_t *)buffer; priv->remaining = buflen; @@ -2265,15 +2315,10 @@ static int mpfs_dmasendsetup(struct sdio_dev_s *dev, mcinfo("Send: %zu bytes\n", buflen); DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); - DEBUGASSERT(((uintptr_t)buffer & 3) == 0); - - /* DMA send doesn't work in 0x08xxxxxxx address range. Default to IRQ mode - * in this special case. - */ - - if (((uintptr_t)buffer & 0xff000000) == 0x08000000) + if (((uintptr_t)buffer & 3) != 0) { - return mpfs_sendsetup(dev, buffer, buflen); + mcerr("Unaligned buffer: %p\n", buffer); + return -EFAULT; } /* Save the source buffer information for use by the interrupt handler */ @@ -2948,7 +2993,7 @@ static void mpfs_callback(void *arg) ****************************************************************************/ /**************************************************************************** - * Name: sdio_initialize + * Name: mpfs_emmcsd_sdio_initialize * * Description: * Initialize SDIO for operation. @@ -2962,7 +3007,7 @@ static void mpfs_callback(void *arg) * ****************************************************************************/ -struct sdio_dev_s *sdio_initialize(int slotno) +struct sdio_dev_s *mpfs_emmcsd_sdio_initialize(int slotno) { struct mpfs_dev_s *priv = NULL; priv = &g_emmcsd_dev; @@ -2973,14 +3018,14 @@ struct sdio_dev_s *sdio_initialize(int slotno) if (!mpfs_device_reset(&priv->dev)) { - return NULL; + return (struct sdio_dev_s *)NULL; } - return &priv->dev; + return (struct sdio_dev_s *) &priv->dev; } /**************************************************************************** - * Name: sdio_mediachange + * Name: mpfs_emmcsd_sdio_mediachange * * Description: * Called by board-specific logic -- possible from an interrupt handler -- @@ -2998,7 +3043,7 @@ struct sdio_dev_s *sdio_initialize(int slotno) * ****************************************************************************/ -void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) +void mpfs_emmcsd_sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) { struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev; sdio_statset_t cdstatus; @@ -3031,7 +3076,7 @@ void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) } /**************************************************************************** - * Name: sdio_wrprotect + * Name: mpfs_emmcsd_sdio_wrprotect * * Description: * Called by board-specific logic to report if the card in the slot is @@ -3046,7 +3091,7 @@ void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) * ****************************************************************************/ -void sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect) +void mpfs_emmcsd_sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect) { struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev; irqstate_t flags; diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.h b/arch/risc-v/src/mpfs/mpfs_emmcsd.h index 3f1e0f562453d..40e90a91dccd9 100644 --- a/arch/risc-v/src/mpfs/mpfs_emmcsd.h +++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.h @@ -48,7 +48,7 @@ extern "C" #endif /**************************************************************************** - * Name: sdio_initialize + * Name: mpfs_emmcsd_sdio_initialize * * Description: * Initialize SDIO for operation. @@ -63,10 +63,10 @@ extern "C" ****************************************************************************/ struct sdio_dev_s; /* See include/nuttx/sdio.h */ -struct sdio_dev_s *sdio_initialize(int slotno); +struct sdio_dev_s *mpfs_emmcsd_sdio_initialize(int slotno); /**************************************************************************** - * Name: sdio_mediachange + * Name: mpfs_emmcsd_sdio_mediachange * * Description: * Called by board-specific logic -- possibly from an interrupt handler -- @@ -84,10 +84,10 @@ struct sdio_dev_s *sdio_initialize(int slotno); * ****************************************************************************/ -void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot); +void mpfs_emmcsd_sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot); /**************************************************************************** - * Name: sdio_wrprotect + * Name: mpfs_emmcsd_sdio_wrprotect * * Description: * Called by board-specific logic to report if the card in the slot is @@ -102,7 +102,7 @@ void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot); * ****************************************************************************/ -void sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect); +void mpfs_emmcsd_sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect); #undef EXTERN #if defined(__cplusplus) diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.c b/arch/risc-v/src/mpfs/mpfs_entrypoints.c index 2480253f783e6..fdcbc1a3b4d56 100644 --- a/arch/risc-v/src/mpfs/mpfs_entrypoints.c +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.c @@ -221,4 +221,28 @@ int mpfs_set_use_sbi(uint64_t hartid, bool use_sbi) return ERROR; } +/**************************************************************************** + * Name: mpfs_get_use_sbi + * + * Description: + * Get if hart boots via SBI. + * + * Input Parameters: + * hartid - hart id to check + * + * Returned value: + * true if SBI is used, false otherwise + * + ****************************************************************************/ + +bool mpfs_get_use_sbi(uint64_t hartid) +{ + if (hartid < ENTRYPT_CNT) + { + return (g_hart_use_sbi & (1 << hartid)) != 0; + } + + return false; +} + #endif /* CONFIG_MPFS_BOOTLOADER */ diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.h b/arch/risc-v/src/mpfs/mpfs_entrypoints.h index 949972db74f2c..794b01974a691 100644 --- a/arch/risc-v/src/mpfs/mpfs_entrypoints.h +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.h @@ -86,6 +86,22 @@ int mpfs_set_entrypt(uint64_t hartid, uintptr_t entry); int mpfs_set_use_sbi(uint64_t hartid, bool use_sbi); +/**************************************************************************** + * Name: mpfs_get_use_sbi + * + * Description: + * Get if hart boots via SBI. + * + * Input Parameters: + * hartid - hart id to check + * + * Returned value: + * true if SBI is used, false otherwise + * + ****************************************************************************/ + +bool mpfs_get_use_sbi(uint64_t hartid); + #if defined(__cplusplus) } #endif diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index 382477fa9e60e..bea93cc80ab65 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -101,7 +101,7 @@ # elif defined(CONFIG_MPFS_ETHMAC_LPWORK) # define ETHWORK LPWORK # else -# define ETHWORK LPWORK +# define ETHWORK HPWORK # endif #endif @@ -171,6 +171,10 @@ #define MPFS_TXTIMEOUT (60 * CLK_TCK) +/* RX timeout = 30s */ + +#define MPFS_RXTIMEOUT (30 * CLK_TCK) + /* PHY reset tim in loop counts */ #define PHY_RESET_WAIT_COUNT (10) @@ -268,6 +272,7 @@ struct mpfs_ethmac_s uint8_t phyaddr; /* PHY address */ #endif struct wdog_s txtimeout; /* TX timeout timer */ + struct wdog_s rxtimeout; /* RX timeout timer */ struct work_s irqwork; /* For deferring interrupt work to the work queue */ struct work_s pollwork; /* For deferring poll work to the work queue */ @@ -389,6 +394,7 @@ static int mpfs_ethconfig(struct mpfs_ethmac_s *priv); static void mpfs_ethreset(struct mpfs_ethmac_s *priv); static void mpfs_interrupt_work(void *arg); +static void mpfs_txtimeout_expiry(wdparm_t arg); /**************************************************************************** * Private Functions @@ -470,6 +476,14 @@ static int mpfs_interrupt_0(int irq, void *context, void *arg) wd_cancel(&priv->txtimeout); } + if ((isr & GEM_INT_RECEIVE_COMPLETE) != 0) + { + /* If a RX transfer just completed, restart the timeout */ + + wd_start(&priv->rxtimeout, MPFS_RXTIMEOUT, + mpfs_txtimeout_expiry, (wdparm_t)priv); + } + /* Schedule to perform the interrupt processing on the worker thread. */ work_queue(ETHWORK, &priv->irqwork, mpfs_interrupt_work, priv, 0); @@ -1558,6 +1572,13 @@ static int mpfs_ifup(struct net_driver_s *dev) up_enable_irq(priv->mac_q_int[2]); up_enable_irq(priv->mac_q_int[3]); + /* Set up the RX timeout. If we don't receive anything in time, try + * to re-initialize + */ + + wd_start(&priv->rxtimeout, MPFS_RXTIMEOUT, + mpfs_txtimeout_expiry, (wdparm_t)priv); + return OK; } @@ -1601,6 +1622,10 @@ static int mpfs_ifdown(struct net_driver_s *dev) wd_cancel(&priv->txtimeout); + /* Cancel the RX timeout timers */ + + wd_cancel(&priv->rxtimeout); + /* Put the MAC in its reset, non-operational state. This should be * a known configuration that will guarantee the mpfs_ifup() always * successfully brings the interface back up. diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c new file mode 100644 index 0000000000000..fd76bc5187ea1 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -0,0 +1,3081 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_fpga_canfd.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mpfs_fpga_canfd.h" +#include "riscv_internal.h" +#include "mpfs_memorymap.h" + +#include "hardware/mpfs_fpga_canfd.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef OK +# define OK 0 +#endif + +/* This module only compiles if the CANFD IP core instance + * is configured to the FPGA + */ + +#ifndef CONFIG_MPFS_HAVE_CANFD +# error This should not be compiled as CANFD FPGA block is not defined +#endif + +/* This module only compiles if Nuttx socketCAN interface supports CANFD */ + +#ifndef CONFIG_NET_CAN_CANFD +# error This should not be compiled as CANFD driver relies on socket CAN +#endif + +/* Clock reset and enabling */ + +#define MPFS_SYSREG_SOFT_RESET_CR (MPFS_SYSREG_BASE + \ + MPFS_SYSREG_SOFT_RESET_CR_OFFSET) +#define MPFS_SYSREG_SUBBLK_CLOCK_CR (MPFS_SYSREG_BASE + \ + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET) + +#define CANWORK HPWORK + +#define MPFS_CANFD_ID 0xCAFD + +/* For allocating the tx and rx CANFD frame buffer */ + +#define POOL_SIZE 1 +#define TIMESTAMP_SIZE sizeof(struct timeval) /* To support + * timestamping frame */ + +/* For bit timing calculation */ + +#define BT_COMPUTE_MAX_ERROR 50 /* 1/10th of % */ +#define BT_COMPUTE_SYNC_SEG 1 + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +/* CAN hw filter support */ + +#define HW_FILTER_A 0 +#define HW_FILTER_B 1 +#define HW_FILTER_C 2 +#define HW_FILTER_RANGE 3 + +#define CAN_STD_ID 0 +#define CAN_EXT_ID 1 +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +/* Special address description flags for the CAN_ID */ + +#define CAN_EFF_FLAG 0x80000000 /* EFF/SFF is set in the MSB */ +#define CAN_RTR_FLAG 0x40000000 /* remote transmission request */ +#define CAN_ERR_FLAG 0x20000000 /* error message frame */ + +/* Valid bits in CAN ID for frame formats */ + +#define CAN_SFF_MASK 0x000007FF /* standard frame format (SFF) */ +#define CAN_EFF_MASK 0x1FFFFFFF /* extended frame format (EFF) */ +#define CAN_ERR_MASK 0x1FFFFFFF /* omit EFF, RTR, ERR flags */ + +/* CAN control mode */ + +#define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ +#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ +#define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ +#define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ +#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ +#define CAN_CTRLMODE_FD 0x20 /* CAN FD mode */ +#define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */ +#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */ +#define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */ +#define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically + * calculates TDCV */ +#define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */ + +/* TXT buffer */ + +enum mpfs_can_txb_status +{ + TXT_NOT_EXIST = 0x0, + TXT_RDY = 0x1, + TXT_TRAN = 0x2, + TXT_ABTP = 0x3, + TXT_TOK = 0x4, + TXT_ERR = 0x6, + TXT_ABT = 0x7, + TXT_ETY = 0x8, +}; + +enum mpfs_can_txb_command +{ + TXT_CMD_SET_EMPTY = 0x01, + TXT_CMD_SET_READY = 0x02, + TXT_CMD_SET_ABORT = 0x04 +}; + +/**************************************************************************** + * Utility definitions + ****************************************************************************/ + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define clamp(val, lo, hi) min(max(val, lo), hi) + +#define MPFS_CAN_FD_TXNF(priv) \ + (getreg32(priv->base + MPFS_CANFD_STATUS_OFFSET) & MPFS_CANFD_STATUS_TXNF) +#define MPFS_CAN_FD_ENABLED(priv) \ + (getreg32(priv->base + MPFS_CANFD_MODE_OFFSET) & MPFS_CANFD_MODE_ENA) + +#if __GNUC__ >= 3 +# define expect(expr,value) __builtin_expect((expr),(value)) +#else +# define expect(expr,value) (expr) +#endif + +#define expect_false(expr) expect((expr) != 0, 0) +#define expect_true(expr) expect((expr) != 0, 1) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* CAN operational and error states */ + +/* CAN bit timing parameters */ + +struct mpfs_can_bittiming_s +{ + uint32_t bitrate; /* Bit-rate in bits/second */ + uint32_t sample_point; /* Sample point in one-tenth of a percent */ + uint32_t tq; /* Time quanta (TQ) in nanoseconds */ + uint32_t prop_seg; /* Propagation segment in TQs */ + uint32_t phase_seg1; /* Phase buffer segment 1 in TQs */ + uint32_t phase_seg2; /* Phase buffer segment 2 in TQs */ + uint32_t sjw; /* Synchronisation jump width in TQs */ + uint32_t brp; /* Bitrate prescaler */ +}; + +/* CAN harware dependent bit timing constants + * Used for calculating and checking bit timing parameters + */ + +struct mpfs_can_bittiming_const_s +{ + uint32_t tseg_min; + uint32_t tseg_max; + uint32_t brp_min; + uint32_t brp_max; +}; + +static const struct mpfs_can_bittiming_const_s mpfs_can_bit_timing_range = +{ + .tseg_min = 3, + .tseg_max = 253, + .brp_min = 1, + .brp_max = 8, +}; + +static const struct mpfs_can_bittiming_const_s + mpfs_can_bit_timing_data_range = +{ + .tseg_min = 3, + .tseg_max = 125, + .brp_min = 1, + .brp_max = 2, +}; + +struct mpfs_can_clock_s +{ + uint32_t freq; /* CAN system clock frequency in Hz */ +}; + +enum mpfs_can_state_e +{ + CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */ + CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */ + CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */ + CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */ + CAN_STATE_STOPPED, /* Device is stopped */ + CAN_STATE_SLEEPING, /* Device is sleeping */ + CAN_STATE_MAX +}; + +struct mpfs_can_ctrlmode_s +{ + uint32_t mask; + uint32_t flags; +}; + +struct mpfs_can_berr_counter_s +{ + uint16_t txerr; + uint16_t rxerr; +}; + +struct mpfs_can_device_stats_s +{ + uint32_t bus_error; /* Bus errors */ + uint32_t error_warning; /* Changes to error warning state */ + uint32_t error_passive; /* Changes to error passive state */ + uint32_t bus_off; /* Changes to bus off state */ + uint32_t arbitration_lost; /* Arbitration lost errors */ + uint32_t restarts; /* CAN controller re-starts */ +}; + +/* CAN common private data */ + +struct mpfs_can_priv_s +{ + struct mpfs_can_device_stats_s can_stats; + struct mpfs_can_bittiming_s bittiming; + struct mpfs_can_bittiming_s data_bittiming; + const struct mpfs_can_bittiming_const_s *bittiming_const; + const struct mpfs_can_bittiming_const_s *data_bittiming_const; + struct mpfs_can_clock_s clock; + + enum mpfs_can_state_e state; + uint32_t ctrlmode; +}; + +/**************************************************************************** + * CANFD Frame Format + ****************************************************************************/ + +/* CAN frame format memory map */ + +enum mpfs_canfd_can_frame_format +{ + MPFS_CANFD_FRAME_FORMAT_W_OFFSET = 0x0, + MPFS_CANFD_IDENTIFIER_W_OFFSET = 0x4, + MPFS_CANFD_TIMESTAMP_L_W_OFFSET = 0x8, + MPFS_CANFD_TIMESTAMP_U_W_OFFSET = 0xc, + MPFS_CANFD_DATA_1_4_W_OFFSET = 0x10, + MPFS_CANFD_DATA_5_8_W_OFFSET = 0x14, + MPFS_CANFD_DATA_61_64_W_OFFSET = 0x4c, +}; + +/* CANFD_Frame_format memory region */ + +/* FRAME_FORMAT_W registers */ + +#define MPFS_CANFD_FRAME_FORMAT_W_DLC_SHIFT (0) +#define MPFS_CANFD_FRAME_FORMAT_W_DLC (0x0F << \ + MPFS_CANFD_FRAME_FORMAT_W_DLC_SHIFT) +#define MPFS_CANFD_FRAME_FORMAT_W_RTR (1 << 5) +#define MPFS_CANFD_FRAME_FORMAT_W_IDE (1 << 6) +#define MPFS_CANFD_FRAME_FORMAT_W_FDF (1 << 7) +#define MPFS_CANFD_FRAME_FORMAT_W_BRS (1 << 9) +#define MPFS_CANFD_FRAME_FORMAT_W_ESI_RSV (1 << 10) +#define MPFS_CANFD_FRAME_FORMAT_W_RWCNT_SHIFT (11) +#define MPFS_CANFD_FRAME_FORMAT_W_RWCNT (0x1F << \ + MPFS_CANFD_FRAME_FORMAT_W_RWCNT_SHIFT) + +/* IDENTIFIER_W registers */ + +#define MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT_SHIFT (0) +#define MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT (0x03FFFF << \ + MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT_SHIFT) +#define MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT (18) +#define MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE (0x07FF << \ + MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT) + +/**************************************************************************** + * CAN controller hardware configuration + ****************************************************************************/ + +struct mpfs_config_s +{ + uint32_t canfd_fpga_irq; /* the only CANFD FPGA IRQ */ +}; + +#ifdef CONFIG_MPFS_CANFD0 +static const struct mpfs_config_s mpfs_fpga_canfd_config0 = +{ + .canfd_fpga_irq = MPFS_IRQ_FABRIC_F2H_0, +}; +#endif +#ifdef CONFIG_MPFS_CANFD1 +static const struct mpfs_config_s mpfs_fpga_canfd_config1 = +{ + .canfd_fpga_irq = MPFS_IRQ_FABRIC_F2H_9, +}; +#endif + +/**************************************************************************** + * The mpfs_driver_s encapsulates all state information for a single + * hw interface + ****************************************************************************/ + +struct mpfs_driver_s +{ + struct mpfs_can_priv_s can; + + const struct mpfs_config_s *config; + + uintptr_t base; /* CANFD FPGA base address */ + bool bifup; /* true:ifup false:ifdown */ + + struct work_s rxwork; /* for deferring rx interrupt work to the wq */ + struct work_s txdwork; /* For deferring tx done interrupt work to the + * wq */ + struct work_s pollwork; /* For deferring poll work to the wq */ + + struct canfd_frame *txdesc; /* A pointer to the list of TX descriptor */ + struct canfd_frame *rxdesc; /* A pointer to the list of RX descriptors */ + + /* rx */ + + uint32_t drv_flags; /* driver flag */ + uint32_t rxfrm_first_word; /* rx frame first word (usually a FFW) */ + + /* tx */ + + unsigned int txb_sent; + unsigned int txb_processed; + uint32_t txb_prio; + unsigned int ntxbufs; + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + /* hw filter */ + + uint8_t used_bit_filter_number; + bool used_range_filter; +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + + /* This holds the information visible to the NuttX network */ + + struct net_driver_s dev; /* Interface understood by the network */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_MPFS_CANFD0 +static struct mpfs_driver_s g_canfd0; + +static uint8_t g_tx_pool0[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * + POOL_SIZE]; +static uint8_t g_rx_pool0[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * + POOL_SIZE]; +#endif + +#ifdef CONFIG_MPFS_CANFD1 +static struct mpfs_driver_s g_canfd1; + +static uint8_t g_tx_pool1[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * + POOL_SIZE]; +static uint8_t g_rx_pool1[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * + POOL_SIZE]; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* (from interrupt) RX related functions */ + +static bool mpfs_can_retrieve_rx_frame(struct mpfs_driver_s *priv, + struct canfd_frame *cf, + uint32_t ffw); +static void mpfs_receive_work(void *arg); + +/* (from interrupt) TX related functions */ + +static void mpfs_can_update_txb_prio(struct mpfs_driver_s *priv); +static void mpfs_can_send_txb_cmd(struct mpfs_driver_s *priv, + enum mpfs_can_txb_command cmd, + uint8_t buf); +static bool mpfs_txdone(struct mpfs_driver_s *priv); +static void mpfs_txdone_work(void *arg); + +/* (from interrupt) Error handling related functions */ + +static enum mpfs_can_state_e + mpfs_can_get_err_state(struct mpfs_driver_s *priv); +static void mpfs_can_get_err_count(struct mpfs_driver_s *priv, + struct mpfs_can_berr_counter_s *bec); +static void mpfs_err_interrupt(struct mpfs_driver_s *priv, uint32_t isr); + +/* Interrupt service routine */ + +static int mpfs_interrupt(int irq, void *context, void *arg); + +/* (Nuttx network driver interface callback when TX packet available) Tx + * related functions + */ + +static enum mpfs_can_txb_status + mpfs_can_get_txb_status(struct mpfs_driver_s *priv, + uint8_t buf); +static bool mpfs_can_is_txb_writable(struct mpfs_driver_s *priv, + uint8_t buf); +static bool mpfs_can_write_txb(struct mpfs_driver_s *priv, + const struct canfd_frame *cf, + uint8_t buf, + bool is_ccf); +static int mpfs_transmit(struct mpfs_driver_s *priv); +static int mpfs_txpoll(struct net_driver_s *dev); +static void mpfs_txavail_work(void *arg); +static int mpfs_txavail(struct net_driver_s *dev); + +/* Bit timing related functions */ + +static int + mpfs_can_btr_compute(struct mpfs_driver_s *priv, + struct mpfs_can_bittiming_s *bt, + const struct mpfs_can_bittiming_const_s *btc); + +static int mpfs_can_config_bit_timing(struct mpfs_driver_s *priv, + struct mpfs_can_bittiming_s *bt, + bool arbi); +static int mpfs_can_config_arbi_bit_timing(struct mpfs_driver_s *priv); +static int mpfs_can_config_data_bit_timing(struct mpfs_driver_s *priv); + +/* Miscellaneous CAN controller interface functions */ + +static int mpfs_can_config_ssp(struct mpfs_driver_s *priv); +static void + mpfs_can_config_controller_mode(struct mpfs_driver_s *priv, + const struct mpfs_can_ctrlmode_s *mode); + +/* HW filter related functions */ + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, + uint8_t filter_type, + uint8_t can_id_type, + uint8_t can_type, + uint32_t fid1, + uint32_t fid2); +static void mpfs_can_reset_hw_filter(struct mpfs_driver_s *priv); +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +/* CAN controller life cycle routines */ + +static int mpfs_can_controller_start(struct mpfs_driver_s *priv); +static void mpfs_can_controller_stop(struct mpfs_driver_s *priv); +static int mpfs_reset(struct mpfs_driver_s *priv); + +/* Driver interface to Nuttx network callbacks */ + +static int mpfs_ifup(struct net_driver_s *dev); +static int mpfs_ifdown(struct net_driver_s *dev); +#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); +#endif + +/**************************************************************************** + * Private Function + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_can_read_frame_data + * + * Description: + * Retrieve 4 bytes of CAN/CANFD frame data from RX Buffer + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * data - Pointer to data to be written + * + * Returned Value: + * true if data was read successfulle + * false if buffer is empty or next data would be the frame format word + * + ****************************************************************************/ + +static bool mpfs_can_read_frame_data(struct mpfs_driver_s *priv, + uint32_t *data) +{ + uint32_t rx_status = getreg32(priv->base + MPFS_CANFD_RX_STATUS_OFFSET); + if ((rx_status & MPFS_CANFD_RX_STATUS_RXMOF) == 0 || + (rx_status & MPFS_CANFD_RX_STATUS_RXE) != 0) + { + /* Reached the beginning of the next frame or buffer is empty */ + + return false; + } + + *data = getreg32(priv->base + MPFS_CANFD_RX_DATA_OFFSET); + return true; +} + +/**************************************************************************** + * Name: mpfs_can_retrieve_rx_frame + * + * Description: + * Retrieve CAN/CANFD frame from RX Buffer + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * cf - Pointer to CANFD frame structure + * ffw - Previously read frame format word + * + * Returned Value: + * true if frame was read successfully, false otherwise + * + * Assumptions: + * Frame format word is already parsed in advance and provided as 'ffw' arg + * + ****************************************************************************/ + +static bool mpfs_can_retrieve_rx_frame(struct mpfs_driver_s *priv, + struct canfd_frame *cf, + uint32_t ffw) +{ + uint32_t idw; + uint32_t tmp; + unsigned int i; + unsigned int data_wc; /* data word count */ + unsigned int data_bc; /* data byte count */ + unsigned int dlc; + unsigned int len; + + /* CAN ID */ + + if (!mpfs_can_read_frame_data(priv, &idw)) + { + return false; + } + + if (MPFS_CANFD_FRAME_FORMAT_W_IDE & ffw) + { + cf->can_id = (idw & CAN_EFF_MASK) | CAN_EFF_FLAG; + } + else + { + cf->can_id = + (idw >> MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT) & + CAN_SFF_MASK; + } + + /* BRS, ESI, RTR Flags */ + + cf->flags = 0; + if (MPFS_CANFD_FRAME_FORMAT_W_FDF & ffw) + { + /* Enable bitrate switch by default if frame is CANFD */ + + cf->flags |= CANFD_BRS; + + if (MPFS_CANFD_FRAME_FORMAT_W_ESI_RSV & ffw) + { + cf->flags |= CANFD_ESI; + } + } + else if (MPFS_CANFD_FRAME_FORMAT_W_RTR & ffw) + { + cf->can_id |= CAN_RTR_FLAG; + } + + /* RWCNT : RX Count of Words without FRAME_FORMAT WORD. Minus the 3 words + * for 1 IDW, 2 timestamp words + */ + + data_wc = ((MPFS_CANFD_FRAME_FORMAT_W_RWCNT & ffw) >> + MPFS_CANFD_FRAME_FORMAT_W_RWCNT_SHIFT) - 3; + data_bc = data_wc * 4; + + /* DLC */ + + dlc = (MPFS_CANFD_FRAME_FORMAT_W_DLC & ffw) >> + MPFS_CANFD_FRAME_FORMAT_W_DLC_SHIFT; + if (dlc <= 8) + { + len = dlc; + } + else + { + if (MPFS_CANFD_FRAME_FORMAT_W_FDF & ffw) + { + len = data_wc << 2; + } + else + { + len = 8; + } + } + cf->len = len; + if (expect_false(len > data_bc)) + { + len = data_bc; + } + + /* Timestamp - Read and throw away */ + + if (!mpfs_can_read_frame_data(priv, &tmp) || + !mpfs_can_read_frame_data(priv, &tmp)) + { + return false; + } + + /* Data */ + + for (i = 0; i < len; i += 4) + { + uint32_t data; + if (!mpfs_can_read_frame_data(priv, &data)) + { + return false; + } + + *(uint32_t *)(cf->data + i) = data; + } + + return true; +} + +/**************************************************************************** + * Name: mpfs_receive_work + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void mpfs_receive_work(void *arg) +{ + struct mpfs_driver_s *priv = (struct mpfs_driver_s *)arg; + + uint32_t status; + uint32_t frame_count; + uint32_t tmp; + bool is_classical_can_frame = false; + + frame_count = (getreg32(priv->base + MPFS_CANFD_RX_STATUS_OFFSET) & + MPFS_CANFD_RX_STATUS_RXFRC) >> MPFS_CANFD_RX_STATUS_RXFRC_SHIFT; + while (frame_count) + { + struct canfd_frame *cf = (struct canfd_frame *)priv->rxdesc; + uint32_t ffw; + + /* Error recovery: if for any reason the RX buffer pointer points to + * a middle of a frame, read until the start of the first frame is + * found. This may happen after bus errors or rx overflow. + */ + + while (mpfs_can_read_frame_data(priv, &tmp)); + + ffw = getreg32(priv->base + MPFS_CANFD_RX_DATA_OFFSET); + + if (!(MPFS_CANFD_FRAME_FORMAT_W_RWCNT & ffw)) + { + break; + } + + if (!(MPFS_CANFD_FRAME_FORMAT_W_FDF & ffw)) + { + if (MPFS_CANFD_FRAME_FORMAT_W_RTR & ffw) + { + caninfo("Remote Frame received\n"); + } + else + { + caninfo("Classical CAN Frame received\n"); + } + + is_classical_can_frame = true; + } + else + { + caninfo("CANFD Frame received\n"); + } + + /* Retrieve the classical or CANFD or remote frame */ + + if (!mpfs_can_retrieve_rx_frame(priv, cf, ffw)) + { + /* Didn't receive full frame, bail out */ + + goto out; + } + + /* Lock the network; we have to protect the dev.d_len, dev.d_buf + * and dev.d_iob from the devif_poll path + */ + + net_lock(); + + /* Copy the buffer pointer to priv->dev.. Set amount of data + * in priv->dev.d_len + */ + + priv->dev.d_len = is_classical_can_frame ? + sizeof(struct can_frame) : sizeof(struct canfd_frame); + priv->dev.d_buf = (uint8_t *)cf; + + /* Send to socket interface */ + + NETDEV_RXPACKETS(&priv->dev); + can_input(&priv->dev); + + net_unlock(); + + /* Point the packet buffer back to the next Tx buffer that will be + * used during the next write. If the write queue is full, then + * this will point at an active buffer, which must not be written + * to. This is OK because devif_poll won't be called unless the + * queue is not full. + */ + + priv->dev.d_buf = (uint8_t *)priv->txdesc; + + frame_count = (getreg32(priv->base + MPFS_CANFD_RX_STATUS_OFFSET) & + MPFS_CANFD_RX_STATUS_RXFRC) >> MPFS_CANFD_RX_STATUS_RXFRC_SHIFT; + } + +out: + + /* Check for RX FIFO Overflow */ + + status = getreg32(priv->base + MPFS_CANFD_STATUS_OFFSET); + if (MPFS_CANFD_STATUS_DOR & status) + { + /* Clear and re-enable Data Overrun interrupt */ + + putreg32(MPFS_CANFD_COMMAND_CDO, + priv->base + MPFS_CANFD_COMMAND_OFFSET); + putreg32(MPFS_CANFD_INT_STAT_DOI, + priv->base + MPFS_CANFD_INT_MASK_CLR_OFFSET); + } + + /* Clear and re-enable RBNEI */ + + putreg32(MPFS_CANFD_INT_STAT_RBNEI, + priv->base + MPFS_CANFD_INT_STAT_OFFSET); + putreg32(MPFS_CANFD_INT_STAT_RBNEI, + priv->base + MPFS_CANFD_INT_MASK_CLR_OFFSET); +} + +/**************************************************************************** + * Name: mpfs_can_update_txb_prio + * + * Description: + * Rotates priorities of TXT buffers + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void mpfs_can_update_txb_prio(struct mpfs_driver_s *priv) +{ + uint32_t prio = priv->txb_prio; + + /* Rotate TX_PRIORITY register states one step left */ + + prio = (prio << 4) | ((prio >> ((priv->ntxbufs - 1) * 4)) & 0xf); + priv->txb_prio = prio; + putreg32(prio, priv->base + MPFS_CANFD_TX_PRIORITY_OFFSET); +} + +/**************************************************************************** + * Name: mpfs_can_send_txb_cmd + * + * Description: + * Execute a TXT buffer command + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * cmd - Cmd to give + * buf - The TXT buffer index (0-based) + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void mpfs_can_send_txb_cmd(struct mpfs_driver_s *priv, + enum mpfs_can_txb_command cmd, + uint8_t buf) +{ + uint32_t txb_cmd = cmd; + + txb_cmd |= 1 << (buf + 8); + putreg32(txb_cmd, priv->base + MPFS_CANFD_TX_COMMAND_OFFSET); +} + +/**************************************************************************** + * Name: mpfs_txdone + * + * Description: + * Tx done interrupt service rountine + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * true on success, false on any error + * + * Assumptions: + * None + * + ****************************************************************************/ + +static bool mpfs_txdone(struct mpfs_driver_s *priv) +{ + bool first_buffer = true; + bool buffer_processed; + enum mpfs_can_txb_status txb_status; + uint8_t txb_id; + + do + { + buffer_processed = false; + while ((int)(priv->txb_sent - priv->txb_processed) > 0) + { + txb_id = priv->txb_processed % priv->ntxbufs; + txb_status = mpfs_can_get_txb_status(priv, txb_id); + bool other_status = false; + + switch (txb_status) + { + case TXT_TOK: + break; + case TXT_ERR: + canwarn("TXB in Error state\n"); + break; + case TXT_ABT: + canwarn("TXB in Aborted state\n"); + break; + default: + other_status = true; + + if (first_buffer) + { + canerr("TXB#%u not in a finished state (0x%x)!\n", + txb_id, txb_status); + + priv->txb_processed++; + + /* Rotate TXT buffer priority */ + + mpfs_can_update_txb_prio(priv); + + /* Mark current unfinished state TXT buffer as empty */ + + mpfs_can_send_txb_cmd(priv, TXT_CMD_SET_EMPTY, txb_id); + + /* Something is fishy, bail out */ + + return false; + } + break; + } + + if (other_status) + { + break; + } + else + { + priv->txb_processed++; + first_buffer = false; + buffer_processed = true; + + /* Rotate TXT buffer priority */ + + mpfs_can_update_txb_prio(priv); + + /* Mark current finished state TXT buffer as empty */ + + mpfs_can_send_txb_cmd(priv, TXT_CMD_SET_EMPTY, txb_id); + } + } + } + while (buffer_processed); + + return true; +} + +/**************************************************************************** + * Name: mpfs_txdone_work + * + * Description: + * An interrupt was received indicating that the last TX packet(s) is done + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * We are not in an interrupt context so that we can lock the network. + * + ****************************************************************************/ + +static void mpfs_txdone_work(void *arg) +{ + struct mpfs_driver_s *priv = (struct mpfs_driver_s *)arg; + + /* There should be space for a new TX in any event. Poll the network for + * new XMIT data + */ + + net_lock(); + devif_poll(&priv->dev, mpfs_txpoll); + net_unlock(); +} + +/**************************************************************************** + * Name: mpfs_can_get_err_state + * + * Description: + * Reads CAN fault confinement state + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Fault confinement state of controller + * + ****************************************************************************/ + +static enum mpfs_can_state_e + mpfs_can_get_err_state(struct mpfs_driver_s *priv) +{ + u_int32_t ewl_erp_fs_reg, rec_tec_reg, ew_limit, rec_val, tec_val; + + ewl_erp_fs_reg = getreg32(priv->base + MPFS_CANFD_EWL_OFFSET); + rec_tec_reg = getreg32(priv->base + MPFS_CANFD_REC_OFFSET); + + ew_limit = ((ewl_erp_fs_reg & MPFS_CANFD_EWL_EW_LIMIT) >> + MPFS_CANFD_EWL_EW_LIMIT_SHIFT); + rec_val = ((rec_tec_reg & MPFS_CANFD_REC_REC_VAL) >> + MPFS_CANFD_REC_REC_VAL_SHIFT); + tec_val = ((rec_tec_reg & MPFS_CANFD_REC_TEC_VAL) >> + MPFS_CANFD_REC_TEC_VAL_SHIFT); + + if (ewl_erp_fs_reg & MPFS_CANFD_EWL_ERA) + { + if (rec_val < ew_limit && tec_val < ew_limit) + { + return CAN_STATE_ERROR_ACTIVE; + } + else + { + return CAN_STATE_ERROR_WARNING; + } + } + else if (ewl_erp_fs_reg & MPFS_CANFD_EWL_ERP) + { + return CAN_STATE_ERROR_PASSIVE; + } + else if (ewl_erp_fs_reg & MPFS_CANFD_EWL_BOF) + { + return CAN_STATE_BUS_OFF; + } + + canwarn("Invalid FPGA CANFD error state\n"); + return CAN_STATE_ERROR_PASSIVE; +} + +/**************************************************************************** + * Name: mpfs_can_get_err_count + * + * Description: + * Reads CAN RX/TX error counter + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * bec - Pointer to Error counter structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mpfs_can_get_err_count(struct mpfs_driver_s *priv, + struct mpfs_can_berr_counter_s *bec) +{ + uint32_t rec_tec_reg = getreg32(priv->base + MPFS_CANFD_REC_OFFSET); + + bec->rxerr = ((rec_tec_reg & MPFS_CANFD_REC_REC_VAL) >> + MPFS_CANFD_REC_REC_VAL_SHIFT); + bec->txerr = ((rec_tec_reg & MPFS_CANFD_REC_TEC_VAL) >> + MPFS_CANFD_REC_TEC_VAL_SHIFT); +} + +/**************************************************************************** + * Name: mpfs_err_interrupt + * + * Description: + * Error frame ISR + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * isr - Interrupt status register value + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mpfs_err_interrupt(struct mpfs_driver_s *priv, uint32_t isr) +{ + enum mpfs_can_state_e state; + struct mpfs_can_berr_counter_s bec; + uint32_t err_capt_retr_ctr_alc_reg; + uint32_t err_type; + uint32_t err_pos; + uint32_t alc_id_field; + uint32_t alc_bit; + + mpfs_can_get_err_count(priv, &bec); + state = mpfs_can_get_err_state(priv); + err_capt_retr_ctr_alc_reg = + getreg32(priv->base + MPFS_CANFD_ERR_CAPT_OFFSET); + + err_type = ((err_capt_retr_ctr_alc_reg & MPFS_CANFD_ERR_CAPT_ERR_TYPE) >> + MPFS_CANFD_ERR_CAPT_ERR_TYPE_SHIFT); + err_pos = ((err_capt_retr_ctr_alc_reg & MPFS_CANFD_ERR_CAPT_ERR_POS) >> + MPFS_CANFD_ERR_CAPT_ERR_POS_SHIFT); + alc_id_field = + ((err_capt_retr_ctr_alc_reg & MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD) >> + MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD_SHIFT); + alc_bit = ((err_capt_retr_ctr_alc_reg & MPFS_CANFD_ERR_CAPT_ALC_BIT) >> + MPFS_CANFD_ERR_CAPT_ALC_BIT_SHIFT); + + caninfo("ISR = 0x%08x, rxerr %d, txerr %d, error type %u, pos %u, ALC " + "id_field %u, bit %u\n", isr, bec.rxerr, bec.txerr, err_type, + err_pos, alc_id_field, alc_bit); + + /* Check for error warning limit and fault confinement state change */ + + if (MPFS_CANFD_INT_STAT_FCSI & isr || MPFS_CANFD_INT_STAT_EWLI & isr) + { + if (priv->can.state == state) + { + canwarn("No state change! Missed interrupt?\n"); + } + + priv->can.state = state; + + switch (state) + { + case CAN_STATE_BUS_OFF: + priv->can.can_stats.bus_off++; + canwarn("Change to BUS_OFF error state\n"); + break; + case CAN_STATE_ERROR_PASSIVE: + priv->can.can_stats.error_passive++; + canwarn("Change to ERROR_PASSIVE error state\n"); + + /* Mask BERR interrupts */ + + putreg32(MPFS_CANFD_INT_STAT_ALI | MPFS_CANFD_INT_STAT_BEI, + priv->base + MPFS_CANFD_INT_MASK_SET_OFFSET); + break; + case CAN_STATE_ERROR_WARNING: + priv->can.can_stats.error_warning++; + canwarn("Change to ERROR_WARNING error state\n"); + break; + case CAN_STATE_ERROR_ACTIVE: + caninfo("Change to ERROR_ACTIVE error state\n"); + + /* Unmask BERR interrupts */ + + putreg32(MPFS_CANFD_INT_STAT_ALI | MPFS_CANFD_INT_STAT_BEI, + priv->base + MPFS_CANFD_INT_MASK_CLR_OFFSET); + return; + default: + canwarn("Unhandled error state %d\n", state); + break; + } + } + + if (MPFS_CANFD_INT_STAT_ALI & isr) + { + canerr("Arbitration lost\n"); + priv->can.can_stats.arbitration_lost++; + } + + if (MPFS_CANFD_INT_STAT_BEI & isr) + { + canerr("Bus error\n"); + priv->can.can_stats.bus_error++; + } + + if (MPFS_CANFD_INT_STAT_DOI & isr) + { + canerr("DOI interrupt\n"); + + /* Mask the interrupt until it is handled in worker */ + + putreg32(MPFS_CANFD_INT_STAT_DOI, + priv->base + MPFS_CANFD_INT_MASK_SET_OFFSET); + + /* Notify to socket interface */ + + NETDEV_RXERRORS(&priv->dev); + } + + /* Notify to socket interface. */ + + NETDEV_ERRORS(&priv->dev); +} + +/**************************************************************************** + * Name: mpfs_interrupt + * + * Description: + * Three interrupt sources will vector to this function: + * 1. CAN frame transmit interrupt + * 2. CAN frame receive interrupt + * 3. Error interrupt + * + * Input Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + ****************************************************************************/ + +static int mpfs_interrupt(int irq, void *context, void *arg) +{ + struct mpfs_driver_s *priv = (struct mpfs_driver_s *)arg; + + uint32_t isr; + uint32_t icr; + + /* Get the interrupt status */ + + isr = getreg32(priv->base + MPFS_CANFD_INT_STAT_OFFSET); + + /* Receive Buffer Not Empty Interrupt */ + + if (isr & MPFS_CANFD_INT_STAT_RBNEI) + { + /* Mask RBNEI until receive is handled be the worker */ + + icr = MPFS_CANFD_INT_STAT_RBNEI; + putreg32(icr, priv->base + MPFS_CANFD_INT_MASK_SET_OFFSET); + + work_queue(CANWORK, &priv->rxwork, mpfs_receive_work, priv, 0); + } + + /* TXT Buffer HW Command Interrupt */ + + if (isr & MPFS_CANFD_INT_STAT_TXBHCI) + { + /* Handle TX interrupt */ + + if (!mpfs_txdone(priv)) + { + canerr("TXBHCI error\n"); + +#ifdef CONFIG_DEBUG_CAN_INFO + caninfo("txb_sent=0x%08x txb_processed=0x%08x\n", priv->txb_sent, + priv->txb_processed); + for (int i = 0; i < priv->ntxbufs; i++) + { + uint32_t status = mpfs_can_get_txb_status(priv, i); + caninfo("txb[%d] txb status=0x%08x\n", i, status); + } +#endif + /* Notify to socket interface */ + + NETDEV_TXERRORS(&priv->dev); + } + + /* Schedule work to poll for next available tx frame from the + * network. + */ + + work_queue(CANWORK, &priv->txdwork, mpfs_txdone_work, priv, 0); + } + + /* Error Interrupts */ + + if ((isr & (MPFS_CANFD_INT_STAT_EWLI | MPFS_CANFD_INT_STAT_FCSI | + MPFS_CANFD_INT_STAT_ALI | MPFS_CANFD_INT_STAT_BEI | + MPFS_CANFD_INT_STAT_DOI)) != 0) + { + canerr("Some error interrupts: 0x%08x\n", isr); + mpfs_err_interrupt(priv, isr); + } + + /* All interrupts are now handled, clear them */ + + putreg32(isr, priv->base + MPFS_CANFD_INT_STAT_OFFSET); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_get_tx_state + * + * Description: + * Get status of txt buffer + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * buf - txt buffer index to get status of (0-based) + * + * Returned Value: + * Status of txt buffer + * + * Assumptions: + * None + * + ****************************************************************************/ + +static enum mpfs_can_txb_status + mpfs_can_get_txb_status(struct mpfs_driver_s *priv, uint8_t buf) +{ + uint32_t tx_status = getreg32(priv->base + MPFS_CANFD_TX_STATUS_OFFSET); + enum mpfs_can_txb_status status = (tx_status >> (buf * 4)) & 0xf; + + return status; +} + +/**************************************************************************** + * Name: mpfs_can_is_txb_writable + * + * Description: + * Precheck txb state if a new frame can be written + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * buf - txt buffer index to get status of (0-based) + * + * Returned Value: + * True - Frame can be inserted to txt buffer + * False - If attempted, frame will not be inserted to txt buffer + * + * Assumptions: + * None + * + ****************************************************************************/ + +static bool mpfs_can_is_txb_writable(struct mpfs_driver_s *priv, + uint8_t buf) +{ + enum mpfs_can_txb_status buf_status; + + buf_status = mpfs_can_get_txb_status(priv, buf); + if (buf_status == TXT_RDY || buf_status == TXT_TRAN || + buf_status == TXT_ABTP) + { + canwarn("TXT buffer status %d\n", buf_status); + return false; + } + + return true; +} + +/**************************************************************************** + * Name: mpfs_can_write_txb + * + * Description: + * Load CAN frame onto txt buffer on the CAN controller + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * cf - Pointer to the CANFD frame to be inserted + * buf - txt buffer index to which the cf frame is inserted (0-based) + * is_ccf- is classical can frame (bool) + * + * Returned Value: + * True - TXT buffer written successfully + * False - Frame was not written to TXT buffer due to: + * 1. TXT buffer is not writable + * 2. Invalid TXT buffer index + * 3. Invalid frame length + * + * Assumptions: + * None + * + ****************************************************************************/ + +static bool mpfs_can_write_txb(struct mpfs_driver_s *priv, + const struct canfd_frame *cf, + uint8_t buf, + bool is_ccf) +{ + uint32_t buf_base; + uint32_t ffw = 0; + uint32_t idw = 0; + unsigned int i; + + /* Check for invalid txt buffer index */ + + if (buf >= priv->ntxbufs) + { + canerr("Invalid txt buffer index...\n"); + return false; + } + + /* Check if it is possible to insert frame to txt buffer */ + + if (!mpfs_can_is_txb_writable(priv, buf)) + { + canwarn("Not possible to insert frame to txt buffer...\n"); + return false; + } + + /* Check for invalid classical CAN / CANFD frame length */ + + if (cf->len > CANFD_MAX_DLEN || (cf->len > CAN_MAX_DLEN && is_ccf)) + { + canerr("Invalid classical / CANFD CAN frame length...\n"); + return false; + } + + /* Populate frame format word */ + + if (cf->can_id & CAN_RTR_FLAG) /* remote transmission request */ + { + ffw |= MPFS_CANFD_FRAME_FORMAT_W_RTR; + } + + if (cf->can_id & CAN_EFF_FLAG) /* extended frame format (29 bit long id) */ + { + ffw |= MPFS_CANFD_FRAME_FORMAT_W_IDE; + } + + if (!is_ccf) + { + ffw |= MPFS_CANFD_FRAME_FORMAT_W_FDF; /* FD Frame */ + if (cf->flags & CANFD_BRS) + { + ffw |= MPFS_CANFD_FRAME_FORMAT_W_BRS; /* Bit rate switch */ + } + } + + ffw |= MPFS_CANFD_FRAME_FORMAT_W_DLC & (len_to_can_dlc[cf->len] << + MPFS_CANFD_FRAME_FORMAT_W_DLC_SHIFT); + + /* Populate CAN frame id word */ + + if (cf->can_id & CAN_EFF_FLAG) + { + idw = cf->can_id & CAN_EFF_MASK; + } + else + { + idw = MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE & + ((cf->can_id & CAN_SFF_MASK) << + MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT); + } + + /* Write frame id and frame format word */ + + buf_base = (buf + 1) * 0x100; + putreg32(ffw, priv->base + buf_base + MPFS_CANFD_FRAME_FORMAT_W_OFFSET); + putreg32(idw, priv->base + buf_base + MPFS_CANFD_IDENTIFIER_W_OFFSET); + + /* Write CAN data payload */ + + if (!(cf->can_id & CAN_RTR_FLAG)) + { + for (i = 0; i < cf->len; i += 4) + { + uint32_t data = *(uint32_t *)(cf->data + i); + putreg32(data, + priv->base + buf_base + MPFS_CANFD_DATA_1_4_W_OFFSET + i); + } + } + + return true; +} + +/**************************************************************************** + * Name: mpfs_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int mpfs_transmit(struct mpfs_driver_s *priv) +{ + uint32_t txb_id; + bool ok; + bool is_classical_can_frame; + + /* Retrieve the classical CAN / CANFD frame from network device buffer */ + + is_classical_can_frame = + priv->dev.d_len <= sizeof(struct can_frame) ? true : false; + struct canfd_frame *cf = (struct canfd_frame *)priv->dev.d_buf; + + /* Get the current txt buffer ID */ + + txb_id = priv->txb_sent % priv->ntxbufs; + + /* Insert classical CAN/CANFD frame into controller txt bf at txb_id */ + + ok = mpfs_can_write_txb(priv, cf, txb_id, is_classical_can_frame); + if (!ok) + { + canwarn("TXNF set but cannot insert frame into TXT buffer!\n"); + NETDEV_TXERRORS(&priv->dev); + return OK; + } + + /* Now, write to txt buffer seems ok, use txt command to set buffer state + * to READY for xmit. + */ + + mpfs_can_send_txb_cmd(priv, TXT_CMD_SET_READY, txb_id); + priv->txb_sent++; + + /* Increment statistics */ + + NETDEV_TXPACKETS(&priv->dev); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_txpoll + * + * Description: + * The transmitter is available, check if the network has any outgoing + * packets ready to send. This is a callback from devif_poll(). + * devif_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. During normal TX polling + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int mpfs_txpoll(struct net_driver_s *dev) +{ + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + /* Send the packet */ + + mpfs_transmit(priv); + + /* Check if there is room in the device to hold another packet. If + * not, return a non-zero value to terminate the poll. + */ + + if (!MPFS_CAN_FD_TXNF(priv)) + { + return -EBUSY; + } + } + + /* If zero is returned, the polling will continue until all connections + * have been examined. + */ + + return OK; +} + +/**************************************************************************** + * Name: mpfs_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Input Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Called on the higher priority worker thread. + * + ****************************************************************************/ + +static void mpfs_txavail_work(void *arg) +{ + struct mpfs_driver_s *priv = (struct mpfs_driver_s *)arg; + + /* Ignore the notification if the interface is not yet up */ + + if (priv->bifup) + { + /* Check if there is room in the controller to hold another outgoing + * packet. + */ + + if (MPFS_CAN_FD_TXNF(priv)) + { + /* Yes, there is, poll the network for new TXT transmit */ + + net_lock(); + devif_poll(&priv->dev, mpfs_txpoll); + net_unlock(); + } + } +} + +/**************************************************************************** + * Name: mpfs_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * 0 - OK + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int mpfs_txavail(struct net_driver_s *dev) +{ + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; + + if (work_available(&priv->pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + mpfs_txavail_work(priv); + } + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_btr_compute + * + * Description: + * Calculate bit timing values to be written to bit timing register + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * bt - Pointer to the bit timing structure to be set + * btc - Pointer to the constant bit timing structure to be used to set + * the bit timing params + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + * Assumptions: + * Bit timing constants needed to be set in advance on which calculation + * in this function is based + * + ****************************************************************************/ + +static int + mpfs_can_btr_compute(struct mpfs_driver_s *priv, + struct mpfs_can_bittiming_s *bt, + const struct mpfs_can_bittiming_const_s *btc) +{ + /* All measured in number of time quanta (Tq = brp / fsys) + * brp : baud rate prescaler as number of system clock periods + * prop_seg : propagation segment (1..8 Tq) + * phase_seg1 : phase segment 1 (1..8 Tq) + * phase_seg2 : phase segment 2 (1..8 Tq) + * + * tseg1 = prop_seg + phase_seg1 + * tseg2 = phase_seg2 + * tseg = tseg1 + tseg2 + * tsegall = BT_COMPUTE_SYNC_SEG + tseg / 2 + * + * sample point = (BT_COMPUTE_SYNC_SEG + tseg1) / + * (BT_COMPUTE_SYNC_SEG + tseg1 + tseg2) * 1000 + * + * CAN bitrate = 1 / (number_of_Tq * Tq) + */ + + unsigned int calc_br; /* current calculated bitrate */ + unsigned int br_err = 0; /* diff between user set bitrate + * and calculated bitrate */ + unsigned int best_br_err = UINT_MAX; /* best bitrate error */ + + unsigned int nominal_sp; /* nominal sample point either set + * by user or inferred from bitrate + * (CiA recommendation) */ + unsigned int calc_sp; /* calculated sample point */ + unsigned int sp_err; /* diff between and nominal sample + * point and currently calculated + * sample point */ + unsigned int best_sp_err = UINT_MAX; /* best sample point error */ + + unsigned int calc_brp; /* currently calculated bitrate + * prescaler */ + unsigned int best_brp = 0; /* currently calculated bitrate + * prescaler */ + unsigned int tseg_double; + unsigned int tseg_sync; + unsigned int tseg1 = 0; + unsigned int tseg2 = 0; + + /* Get sample point nominal */ + + if (bt->sample_point) + { + nominal_sp = bt->sample_point; + } + else + { + if (bt->bitrate <= 500000) + { + nominal_sp = 875; + } + else if (bt->bitrate <= 800000) + { + nominal_sp = 800; + } + else + { + nominal_sp = 750; + } + } + calc_sp = nominal_sp; + + /* Iterate tseg in possible range to find best bit timing values */ + + for (tseg_double = btc->tseg_max * 2 + 1; + tseg_double >= btc->tseg_min * 2; tseg_double--) + { + tseg_sync = tseg_double / 2 + BT_COMPUTE_SYNC_SEG; + + /* Recalculate bitrate prescaler */ + + calc_brp = priv->can.clock.freq / (tseg_sync * bt->bitrate) + + tseg_double % 2; + + if (calc_brp < btc->brp_min || calc_brp > btc->brp_max) + { + continue; + } + + /* Recalculate bitrate and bitrate error */ + + calc_br = priv->can.clock.freq / (calc_brp * tseg_sync); + + br_err = bt->bitrate - calc_br; + if (br_err > best_br_err) + { + continue; + } + else + { + best_sp_err = UINT_MAX; + } + + /* Now, it seems that we have a better bitrate, recalculate sample + * point, tseg1, tseg2 and sample point error + */ + + tseg2 = clamp(tseg_sync - nominal_sp * tseg_sync / 1000, 1, + btc->tseg_max * 249 / 1000); + tseg1 = tseg_double / 2 - tseg2; + calc_sp = 1000 * (tseg_sync - tseg2) / tseg_sync; + + sp_err = nominal_sp - calc_sp; + if (calc_sp > nominal_sp || sp_err > best_sp_err) + { + continue; + } + + /* Update best values and end condition check */ + + best_brp = calc_brp; + best_br_err = br_err; + best_sp_err = sp_err; + + if (best_br_err == 0 && best_sp_err == 0) + { + break; + } + } + + /* Check bitrate error against limit */ + + if ((uint32_t)best_br_err * 1000 > BT_COMPUTE_MAX_ERROR * bt->bitrate) + { + canerr("Bitrate error %d.%d%% is too high\n", br_err / 10, + br_err % 10); + return -EDOM; + } + + /* Retrieve the best calculated sample point */ + + bt->sample_point = calc_sp; + + /* Retrieve bit timing register components */ + + bt->brp = best_brp; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_config_bit_timing + * + * Description: + * Set CAN controller arbitration or data bitrate bit timing + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * bt - Pointer to Bit timing structure + * arbi - True - Arbitration bit timing, False - Data bit timing + * + * Returned Value: + * Zero (OK) on success, -EPERM if CAN controller is not disabled + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_config_bit_timing(struct mpfs_driver_s *priv, + struct mpfs_can_bittiming_s *bt, + bool arbi) +{ + int max_ph1_len = 31; + uint32_t btr = 0; + + if (MPFS_CAN_FD_ENABLED(priv)) + { + canerr("CAN controller should be disabled to set bit timing\n"); + return -EPERM; + } + + if (arbi) + { + max_ph1_len = 63; + } + + if (bt->phase_seg1 > max_ph1_len) + { + bt->prop_seg += bt->phase_seg1 - max_ph1_len; + bt->phase_seg1 = max_ph1_len; + } + + if (arbi) + { + btr = bt->prop_seg << MPFS_CANFD_BTR_PROP_SHIFT; + btr |= bt->phase_seg1 << MPFS_CANFD_BTR_PH1_SHIFT; + btr |= bt->phase_seg2 << MPFS_CANFD_BTR_PH2_SHIFT; + btr |= bt->brp << MPFS_CANFD_BTR_BRP_SHIFT; + btr |= bt->sjw << MPFS_CANFD_BTR_SJW_SHIFT; + caninfo("Arbitration bitrate: %u, Prop_seg: %u, phase_seg1: %u, " + "phase_seg2: %u, brp: %u, sjw: %u \n", bt->bitrate, + bt->prop_seg, bt->phase_seg1, bt->phase_seg2, bt->brp, + bt->sjw); + putreg32(btr, priv->base + MPFS_CANFD_BTR_OFFSET); + } + else + { + btr = bt->prop_seg << MPFS_CANFD_BTR_FD_PROP_FD_SHIFT; + btr |= bt->phase_seg1 << MPFS_CANFD_BTR_FD_PH1_FD_SHIFT; + btr |= bt->phase_seg2 << MPFS_CANFD_BTR_FD_PH2_FD_SHIFT; + btr |= bt->brp << MPFS_CANFD_BTR_FD_BRP_FD_SHIFT; + btr |= bt->sjw << MPFS_CANFD_BTR_FD_SJW_FD_SHIFT; + caninfo("Data bitrate: %u, Prop_seg: %u, phase_seg1: %u, " + "phase_seg2: %u, brp: %u, sjw: %u \n", bt->bitrate, + bt->prop_seg, bt->phase_seg1, bt->phase_seg2, bt->brp, + bt->sjw); + putreg32(btr, priv->base + MPFS_CANFD_BTR_FD_OFFSET); + } + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_config_arbi_bit_timing + * + * Description: + * Set CAN controller arbitration bit timing + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success, -%EPERM if controller is enabled + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_config_arbi_bit_timing(struct mpfs_driver_s *priv) +{ + struct mpfs_can_bittiming_s *arbi_bt = &priv->can.bittiming; + + /* Set bit timing for arbitration bit rate */ + + return mpfs_can_config_bit_timing(priv, arbi_bt, true); +} + +/**************************************************************************** + * Name: mpfs_can_config_data_bit_timing + * + * Description: + * Set CAN controller data bit timing + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success, -%EPERM if controller is enabled + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_config_data_bit_timing(struct mpfs_driver_s *priv) +{ + struct mpfs_can_bittiming_s *data_bt = &priv->can.data_bittiming; + + /* Set bit timing for data bit rate */ + + return mpfs_can_config_bit_timing(priv, data_bt, false); +} + +/**************************************************************************** + * Name: mpfs_can_config_ssp + * + * Description: + * Set CAN controller secondary sample point. + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success, -EPERM if CAN controller is not disabled + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_config_ssp(struct mpfs_driver_s *priv) +{ + struct mpfs_can_bittiming_s *dbt = &(priv->can.data_bittiming); + int ssp_offset = 0; + uint32_t ssp_cfg = 0; + + if (MPFS_CAN_FD_ENABLED(priv)) + { + canerr("CAN controller should be disabled to set secondary sample " + "point\n"); + return -EPERM; + } + + /* secondary sample point is only used for bitrates > 1 Mbits/s */ + + if (dbt->bitrate > 1000000) + { + ssp_offset = (priv->can.clock.freq / 1000) * + dbt->sample_point / dbt->bitrate; + + if (ssp_offset > 127) + { + canwarn("Secondary sample point offset exceeds 127\n"); + ssp_offset = 127; + } + + ssp_cfg = ssp_offset << MPFS_CANFD_TRV_DELAY_SSP_OFFSET_SHIFT; + ssp_cfg |= 0x1 << MPFS_CANFD_TRV_DELAY_SSP_SRC_SHIFT; + } + + putreg32(ssp_cfg, priv->base + MPFS_CANFD_TRV_DELAY_OFFSET); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_config_controller_mode + * + * Description: + * Configure CAN controller mode + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * mode - Pointer to controller modes to be set + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void + mpfs_can_config_controller_mode(struct mpfs_driver_s *priv, + const struct mpfs_can_ctrlmode_s *mode) +{ + uint32_t mode_reg = getreg32(priv->base + MPFS_CANFD_MODE_OFFSET); + + mode_reg = (mode->flags & CAN_CTRLMODE_LOOPBACK) ? + (mode_reg | MPFS_CANFD_MODE_ILBP) : + (mode_reg & ~MPFS_CANFD_MODE_ILBP); + + mode_reg = (mode->flags & CAN_CTRLMODE_LISTENONLY) ? + (mode_reg | MPFS_CANFD_MODE_BMM) : + (mode_reg & ~MPFS_CANFD_MODE_BMM); + + mode_reg = (mode->flags & CAN_CTRLMODE_FD) ? + (mode_reg | MPFS_CANFD_MODE_FDE) : + (mode_reg & ~MPFS_CANFD_MODE_FDE); + + mode_reg = (mode->flags & CAN_CTRLMODE_PRESUME_ACK) ? + (mode_reg | MPFS_CANFD_MODE_ACF) : + (mode_reg & ~MPFS_CANFD_MODE_ACF); + + mode_reg = (mode->flags & CAN_CTRLMODE_FD_NON_ISO) ? + (mode_reg | MPFS_CANFD_MODE_NISOFD) : + (mode_reg & ~MPFS_CANFD_MODE_NISOFD); + + mode_reg &= ~MPFS_CANFD_MODE_RTRTH; + mode_reg = (mode->flags & CAN_CTRLMODE_ONE_SHOT) ? + (mode_reg | MPFS_CANFD_MODE_RTRLE) : + (mode_reg & ~MPFS_CANFD_MODE_RTRLE); + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + mode_reg |= MPFS_CANFD_MODE_AFM; +#endif + + /* Disable test mode */ + + mode_reg &= ~MPFS_CANFD_MODE_TSTM; + + putreg32(mode_reg, priv->base + MPFS_CANFD_MODE_OFFSET); +} + +/**************************************************************************** + * Name: mpfs_can_add_hw_filter + * + * Description: + * Add new hw filter to CAN Controller + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * filter_type - Filter A, B, C or Range + * can_id_type - std CAN ID / ext CAN ID + * can_type - classical CAN / CANFD + * filter_id1 - filter id 1 (can be filter value for bit filter or range + * low for range filter) + * filter_id2 - filter id 2 (can be filter mask for bit filter or range + * high for range filter) + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, + uint8_t filter_type, + uint8_t can_id_type, + uint8_t can_type, + uint32_t fid1, + uint32_t fid2) +{ + uint32_t fc_reg; + + fc_reg = getreg32(priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Clean up filter control reg */ + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FAFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FAFB; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FANE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FANB; + + /* Transform fid1, fid2 */ + + uint32_t fid1_trans = (can_id_type == CAN_EXT_ID) ? + (MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT & + (fid1 << MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT_SHIFT)) : + (MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE & + (fid1 << MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT)); + + uint32_t fid2_trans = (can_id_type == CAN_EXT_ID) ? + (MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT & + (fid2 << MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT_SHIFT)) : + (MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE & + (fid2 << MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT)); + + switch (filter_type) + { + case HW_FILTER_A: + + /* Set filter control reg for filter A */ + + if (can_type == CAN_MSGPRIO_LOW) + { + /* Classical CAN frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FANE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FANB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FAFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FAFB; + } + else if (can_type == CAN_MSGPRIO_HIGH) + { + /* CANFD frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FAFE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FAFB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FANE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FANB; + } + putreg32(fc_reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Set bit filter value / mask */ + + putreg32(fid1_trans, priv->base + MPFS_CANFD_FILTER_A_VAL_OFFSET); + putreg32(fid2_trans, priv->base + MPFS_CANFD_FILTER_A_MASK_OFFSET); + break; + + case HW_FILTER_B: + + /* Set filter control reg for filter B */ + + if (can_type == CAN_MSGPRIO_LOW) + { + /* Classical CAN frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FBNE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FBNB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FBFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FBFB; + } + else if (can_type == CAN_MSGPRIO_HIGH) + { + /* CANFD frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FBFE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FBFB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FBNE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FBNB; + } + putreg32(fc_reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Set bit filter value / mask */ + + putreg32(fid1_trans, priv->base + MPFS_CANFD_FILTER_B_VAL_OFFSET); + putreg32(fid2_trans, priv->base + MPFS_CANFD_FILTER_B_MASK_OFFSET); + break; + + case HW_FILTER_C: + + /* Set filter control reg for filter C */ + + if (can_type == CAN_MSGPRIO_LOW) + { + /* Classical CAN frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FCNE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FCNB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FCFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FCFB; + } + else if (can_type == CAN_MSGPRIO_HIGH) + { + /* CANFD frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FCFE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FCFB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FCNE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FCNB; + } + putreg32(fc_reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Set bit filter value / mask */ + + putreg32(fid1_trans, priv->base + MPFS_CANFD_FILTER_C_VAL_OFFSET); + putreg32(fid2_trans, priv->base + MPFS_CANFD_FILTER_C_MASK_OFFSET); + break; + + case HW_FILTER_RANGE: + + /* Set filter control reg for filter range */ + + if (can_type == CAN_MSGPRIO_LOW) + { + /* Classical CAN frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FRNE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FRNB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FRFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FRFB; + } + else if (can_type == CAN_MSGPRIO_HIGH) + { + /* CANFD frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FRFE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FRFB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FRNE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FRNB; + } + putreg32(fc_reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Set range filter low / high */ + + putreg32(fid1_trans, priv->base + MPFS_CANFD_FILTER_RAN_LOW_OFFSET); + putreg32(fid2_trans, priv->base + MPFS_CANFD_FILTER_RAN_HIGH_OFFSET); + break; + + default: + + /* Unsupported filter type */ + + break; + } +} +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +/**************************************************************************** + * Name: mpfs_can_reset_hw_filter + * + * Description: + * Reset all hw filters (both bit and range filter) to default settings + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +static void mpfs_can_reset_hw_filter(struct mpfs_driver_s *priv) +{ + uint32_t reg; + + /* Reset filter control */ + + reg = 0; + reg |= MPFS_CANFD_FILTER_CONTROL_FANB; + reg |= MPFS_CANFD_FILTER_CONTROL_FANE; + reg |= MPFS_CANFD_FILTER_CONTROL_FAFB; + reg |= MPFS_CANFD_FILTER_CONTROL_FAFE; + putreg32(reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Reset bit filter A */ + + putreg32(0, priv->base + MPFS_CANFD_FILTER_A_VAL_OFFSET); + putreg32(0, priv->base + MPFS_CANFD_FILTER_A_MASK_OFFSET); + + /* Reset bit filter B */ + + putreg32(0, priv->base + MPFS_CANFD_FILTER_B_VAL_OFFSET); + putreg32(0, priv->base + MPFS_CANFD_FILTER_B_MASK_OFFSET); + + /* Reset bit filter C */ + + putreg32(0, priv->base + MPFS_CANFD_FILTER_C_VAL_OFFSET); + putreg32(0, priv->base + MPFS_CANFD_FILTER_C_MASK_OFFSET); + + /* Reset range filter */ + + putreg32(0, priv->base + MPFS_CANFD_FILTER_RAN_LOW_OFFSET); + putreg32(0, priv->base + MPFS_CANFD_FILTER_RAN_HIGH_OFFSET); + + priv->used_bit_filter_number = 0; + priv->used_range_filter = false; +} +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +/**************************************************************************** + * Name: mpfs_can_controller_start + * + * Description: + * This routine starts the driver. Routine expects that controller is in + * reset state. It setups initial Tx buffers for FIFO priorities, sets + * bittiming, enables interrupts, switches core to operational mode and + * changes controller state to %CAN_STATE_STOPPED. + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success and failure value on error + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_controller_start(struct mpfs_driver_s *priv) +{ + uint32_t int_ena; + uint32_t int_msk; + uint32_t mode_reg; + int err; + struct mpfs_can_ctrlmode_s mode; + + /* Initialize TXT buffer sent / processed counter values */ + + priv->txb_sent = 0; + priv->txb_processed = 0; + + /* Configure TXT buffers priority */ + + priv->txb_prio = 0x01234567; + putreg32(priv->base, priv->base + MPFS_CANFD_TX_PRIORITY_OFFSET); + + /* Configure bit-rates and ssp */ + + err = mpfs_can_config_arbi_bit_timing(priv); + if (err < 0) + { + return err; + } + + err = mpfs_can_config_data_bit_timing(priv); + if (err < 0) + { + return err; + } + + err = mpfs_can_config_ssp(priv); + if (err < 0) + { + return err; + } + + /* Configure modes */ + + mode.flags = priv->can.ctrlmode; + mode.mask = 0xffffffff; + mpfs_can_config_controller_mode(priv, &mode); + + /* Configure interrupts */ + + int_ena = MPFS_CANFD_INT_STAT_RBNEI | + MPFS_CANFD_INT_STAT_TXBHCI | + MPFS_CANFD_INT_STAT_EWLI | + MPFS_CANFD_INT_STAT_FCSI | + MPFS_CANFD_INT_STAT_DOI; + + int_msk = ~int_ena; /* Initially allow all but errors */ + + /* Bus error reporting -> Allow Error/Arb.lost interrupts */ + + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + { + int_ena |= MPFS_CANFD_INT_STAT_ALI | MPFS_CANFD_INT_STAT_BEI; + } + + uint32_t mask = 0xffffffff; + putreg32(mask, priv->base + MPFS_CANFD_INT_MASK_CLR_OFFSET); + putreg32(int_msk, priv->base + MPFS_CANFD_INT_MASK_SET_OFFSET); + putreg32(int_ena, priv->base + MPFS_CANFD_INT_ENA_SET_OFFSET); + + /* Put CAN driver to STOPPED state first, CAN controller will enters + * ERROR_ACTIVE on initial FCSI + */ + + priv->can.state = CAN_STATE_STOPPED; + + /* Enable the CAN controller */ + + mode_reg = getreg32(priv->base + MPFS_CANFD_MODE_OFFSET); + mode_reg |= MPFS_CANFD_MODE_ENA; + putreg32(mode_reg, priv->base + MPFS_CANFD_MODE_OFFSET); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_controller_stop + * + * Description: + * This routine stops the driver. This is the drivers stop routine. It will + * disable the interrupts and disable the CAN controller + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void mpfs_can_controller_stop(struct mpfs_driver_s *priv) +{ + uint32_t mask = 0xffffffff; + uint32_t mode; + + /* Disable interrupts */ + + putreg32(mask, priv->base + MPFS_CANFD_INT_ENA_CLR_OFFSET); + putreg32(mask, priv->base + MPFS_CANFD_INT_MASK_SET_OFFSET); + + /* Disable the CAN controller */ + + mode = getreg32(priv->base + MPFS_CANFD_MODE_OFFSET); + mode &= ~MPFS_CANFD_MODE_ENA; + putreg32(mode, priv->base + MPFS_CANFD_MODE_OFFSET); + + /* Set CAN driver state to STOPPED */ + + priv->can.state = CAN_STATE_STOPPED; +} + +/**************************************************************************** + * Name: mpfs_reset + * + * Description: + * Put the EMAC in the non-operational, reset state + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * OK for success and -ETIMEDOUT for failure + * + * Assumptions: + * + ****************************************************************************/ + +static int mpfs_reset(struct mpfs_driver_s *priv) +{ + uint32_t i = 100; + uint32_t device_id; + + /* Reset FPGA and FIC3, enable clock for FIC3 before RD WR */ + + modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, + SYSREG_SOFT_RESET_CR_FPGA | SYSREG_SOFT_RESET_CR_FIC3, + 0); + modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0, SYSREG_SUBBLK_CLOCK_CR_FIC3); + + /* Reset CAN controller */ + + putreg32(MPFS_CANFD_MODE_RST, priv->base + MPFS_CANFD_MODE_OFFSET); + + /* Check if the device is up again */ + + do + { + device_id = (getreg32(priv->base + MPFS_CANFD_DEVICE_ID_OFFSET) & + MPFS_CANFD_DEVICE_ID_DEVICE_ID) >> + MPFS_CANFD_DEVICE_ID_DEVICE_ID_SHIFT; + + if (device_id == MPFS_CANFD_ID) + { + return OK; + } + + if (!i--) + { + canwarn("Device did not leave reset\n"); + return -ETIMEDOUT; + } + + nxsig_usleep(200); + } + while (1); + + priv->can.can_stats.restarts++; +} + +/**************************************************************************** + * Name: mpfs_ifup + * + * Description: + * NuttX Callback: Start the CAN interface + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int mpfs_ifup(struct net_driver_s *dev) +{ + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; + + if (mpfs_can_controller_start(priv) < 0) + { + canerr("CAN controller start failed\n"); + return -1; + } + + priv->bifup = true; + + priv->dev.d_buf = (uint8_t *)priv->txdesc; + + /* Set interrupts */ + + up_enable_irq(priv->config->canfd_fpga_irq); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_ifdown + * + * Description: + * NuttX Callback: Stop the CAN interface. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_ifdown(struct net_driver_s *dev) +{ + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; + + mpfs_can_controller_stop(priv); + + priv->bifup = false; + return OK; +} + +/**************************************************************************** + * Name: mpfs_ioctl + * + * Description: + * PHY ioctl command handler + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * cmd - ioctl command + * arg - Argument accompanying the command + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + * Assumptions: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL +static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) +{ +#if defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL) || \ +defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; +#endif + int ret; + + switch (cmd) + { +#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL + case SIOCGCANBITRATE: + + /* Get bitrate from the CAN controller */ + + { + struct can_ioctl_data_s *req = + (struct can_ioctl_data_s *)((uintptr_t)arg); + req->arbi_bitrate = priv->can.bittiming.bitrate / 1000; /* kbit/s */ + req->arbi_samplep = priv->can.bittiming.sample_point / 10; + req->data_bitrate = priv->can.data_bittiming.bitrate / 1000; /* kbit/s */ + req->data_samplep = priv->can.data_bittiming.sample_point / 10; + ret = OK; + } + break; + + case SIOCSCANBITRATE: + + /* Set bitrate of the CAN controller */ + + { + struct can_ioctl_data_s *req = + (struct can_ioctl_data_s *)((uintptr_t)arg); + + if (req->arbi_bitrate > 1000) + { + canerr("Arbitration bitrate > 1Mbps is not supported."); + ret = -EINVAL; + break; + } + priv->can.bittiming.bitrate = req->arbi_bitrate * 1000; /* bit/s */ + + if (req->arbi_samplep > 100 || req->arbi_samplep < 0) + { + canerr("Invalid arbitration sample point. " + "Range should be [0,100]%%."); + ret = -EINVAL; + break; + } + priv->can.bittiming.sample_point = + req->arbi_samplep * 10; /* In one-tenth of a percent */ + + if (req->data_bitrate > 4000 || + req->data_bitrate < req->arbi_bitrate) + { + canerr("Data bitrate higher than 4Mbps is yet to be supported. " + "Data br cannot be smaller than arbitration br."); + ret = -EINVAL; + break; + } + priv->can.data_bittiming.bitrate = req->data_bitrate * 1000; /* bit/s */ + + if (req->data_samplep > 100 || req->data_samplep < 0) + { + canerr("Invalid data sample point. Range should be [0,100]%%."); + ret = -EINVAL; + break; + } + priv->can.data_bittiming.sample_point = + req->data_samplep * 10; /* In one-tenth of a percent */ + + /* Calculate arbitration and data bit timing */ + + mpfs_can_btr_compute(priv, + &priv->can.bittiming, + priv->can.bittiming_const); + mpfs_can_btr_compute(priv, + &priv->can.data_bittiming, + priv->can.data_bittiming_const); + + /* CAN controller reset to write bit timing register */ + + mpfs_can_controller_stop(priv); + if (mpfs_can_controller_start(priv) < 0) + { + canerr("CAN controller start failed."); + ret = -1; + break; + } + + ret = OK; + } + break; +#endif /* CONFIG_NETDEV_CAN_BITRATE_IOCTL */ + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + case SIOCACANSTDFILTER: + + { + uint8_t filter; + struct can_ioctl_filter_s *req = + (struct can_ioctl_filter_s *)((uintptr_t)arg); + + if (req->ftype == CAN_FILTER_MASK) + { + if (priv->used_bit_filter_number == 0) + { + /* Use bit filter A */ + + filter = HW_FILTER_A; + } + else if (priv->used_bit_filter_number == 1) + { + /* Use bit filter B */ + + filter = HW_FILTER_B; + } + else if (priv->used_bit_filter_number == 2) + { + /* Use bit filter C */ + + filter = HW_FILTER_C; + } + else + { + /* All bit filters used. Return with error */ + + canerr("All bit filters used. Cannot add more. Delete all and " + "add again."); + ret = -1; + break; + } + priv->used_bit_filter_number++; + } + else if (req->ftype == CAN_FILTER_RANGE) + { + /* Use range filter */ + + filter = HW_FILTER_RANGE; + priv->used_range_filter = true; + } + else + { + /* Dual address and other filter types not yet support */ + + canerr("Dual address and other filter types not yet support"); + ret = -1; + break; + } + + /* Add hw filter */ + + mpfs_can_add_hw_filter(priv, + filter, + CAN_STD_ID, + req->fprio, /* LOW for CAN, HIGH for FDCAN */ + req->fid1, + req->fid2); + + ret = OK; + } + break; + + case SIOCACANEXTFILTER: + + /* Add CAN EXTENDED ID HW FILTER */ + + { + uint8_t filter; + struct can_ioctl_filter_s *req = + (struct can_ioctl_filter_s *)((uintptr_t)arg); + + if (req->ftype == CAN_FILTER_MASK) + { + if (priv->used_bit_filter_number == 0) + { + /* Use bit filter A */ + + filter = HW_FILTER_A; + } + else if (priv->used_bit_filter_number == 1) + { + /* Use bit filter B */ + + filter = HW_FILTER_B; + } + else if (priv->used_bit_filter_number == 2) + { + /* Use bit filter C */ + + filter = HW_FILTER_C; + } + else + { + /* All bit filters used. Return with error */ + + canerr("All bit filters used. Cannot add more. Delete all and " + "add again."); + ret = -1; + break; + } + priv->used_bit_filter_number++; + } + else if (req->ftype == CAN_FILTER_RANGE) + { + /* Use range filter */ + + if (priv->used_range_filter) + { + /* The range filter is already used. Return with error */ + + canerr("Range filter used. Cannot add more. Delete all and " + "add again."); + ret = -1; + break; + } + filter = HW_FILTER_RANGE; + priv->used_range_filter = true; + } + else + { + /* Dual address and other filter types not yet support */ + + canerr("Dual address and other filter types not yet support"); + ret = -1; + break; + } + + /* Add hw filter */ + + mpfs_can_add_hw_filter(priv, + filter, + CAN_EXT_ID, + req->fprio, /* CAN Type: LOW for CAN, HIGH for FDCAN */ + req->fid1, + req->fid2); + + ret = OK; + } + break; + + case SIOCDCANSTDFILTER: + case SIOCDCANEXTFILTER: + + /* Reset all HW FILTERs */ + + { + mpfs_can_reset_hw_filter(priv); + ret = OK; + } + break; +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif /* CONFIG_NETDEV_IOCTL */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_fpga_canfd_init + * + * Description: + * Initialize the CAN controller and driver + * + * Returned Value: + * On success, a pointer to the MPFS CANFD driver is + * returned. NULL is returned on any failure. + * + * Assumptions: + * None + * + ****************************************************************************/ + +int mpfs_fpga_canfd_init(void) +{ +#ifdef CONFIG_MPFS_CANFD0 + caninfo("Initialize CANFD0 driver...\n"); + struct mpfs_driver_s *priv0; + priv0 = &g_canfd0; + memset(priv0, 0, sizeof(struct mpfs_driver_s)); + + priv0->base = CONFIG_MPFS_CANFD_BASE0; + priv0->config = &mpfs_fpga_canfd_config0; + + /* Initialize the CAN common private data structure */ + + priv0->can.state = CAN_STATE_ERROR_ACTIVE; + priv0->ntxbufs = 2; + priv0->can.bittiming_const = &mpfs_can_bit_timing_range; + priv0->can.data_bittiming_const = &mpfs_can_bit_timing_data_range; + + priv0->can.can_stats.arbitration_lost = 0; + priv0->can.can_stats.bus_error = 0; + priv0->can.can_stats.bus_off = 0; + priv0->can.can_stats.error_warning = 0; + priv0->can.can_stats.error_passive = 0; + priv0->can.can_stats.restarts = 0; + + /* Get the can_clk info */ + + priv0->can.clock.freq = MPFS_FPGA_PERIPHERAL_CLK; + + /* Needed for timing adjustment to be performed as soon as possible */ + + priv0->can.bittiming.bitrate = CONFIG_MPFS_CANFD_ARBI_BITRATE0; + priv0->can.data_bittiming.bitrate = CONFIG_MPFS_CANFD_DATA_BITRATE0; + priv0->can.bittiming.sjw = 5; + priv0->can.data_bittiming.sjw = 5; + + /* Calculate nominal and data bit timing */ + + mpfs_can_btr_compute(priv0, + &priv0->can.bittiming, + priv0->can.bittiming_const); + mpfs_can_btr_compute(priv0, + &priv0->can.data_bittiming, + priv0->can.data_bittiming_const); + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + /* Init hw filter runtime var */ + + priv0->used_bit_filter_number = 0; + priv0->used_range_filter = false; +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + + /* Set CAN control modes */ + + priv0->can.ctrlmode = CAN_CTRLMODE_FD + | CAN_CTRLMODE_BERR_REPORTING; + + /* Attach the interrupt handler */ + + if (irq_attach(priv0->config->canfd_fpga_irq, mpfs_interrupt, priv0)) + { + /* We could not attach the ISR to the interrupt */ + + canerr("ERROR: Failed to attach to CAN0 IRQ\n"); + return -EAGAIN; + } + + /* Initialize TX/RX descriptor structure */ + + priv0->txdesc = (struct canfd_frame *)&g_tx_pool0; + priv0->rxdesc = (struct canfd_frame *)&g_rx_pool0; + + /* Initialize the driver network device structure */ + + priv0->dev.d_ifup = mpfs_ifup; /* I/F up (new IP address) callback */ + priv0->dev.d_ifdown = mpfs_ifdown; /* I/F down callback */ + priv0->dev.d_txavail = mpfs_txavail; /* New TX data callback */ +#ifdef CONFIG_NETDEV_IOCTL + priv0->dev.d_ioctl = mpfs_ioctl; /* Support CAN ioctl() calls */ +#endif + priv0->dev.d_private = priv0; /* Used to recover private state from dev */ + + /* Reset controller */ + + if (mpfs_reset(priv0) < 0) + { + return -1; + } + + caninfo("CANFD0 driver init done\n"); + + /* Put the interface in the down state. This usually amounts to resetting + * the device and/or calling mpfs_ifdown(). + */ + + mpfs_ifdown(&priv0->dev); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + netdev_register(&priv0->dev, NET_LL_CAN); +#endif /* CONFIG_MPFS_CANFD0 */ + +#ifdef CONFIG_MPFS_CANFD1 + caninfo("Initialize CANFD1 driver...\n"); + struct mpfs_driver_s *priv1; + priv1 = &g_canfd1; + memset(priv1, 0, sizeof(struct mpfs_driver_s)); + + priv1->base = CONFIG_MPFS_CANFD_BASE1; + priv1->config = &mpfs_fpga_canfd_config1; + + /* Initialize the CAN common private data structure */ + + priv1->can.state = CAN_STATE_ERROR_ACTIVE; + priv1->ntxbufs = 2; + priv1->can.bittiming_const = &mpfs_can_bit_timing_range; + priv1->can.data_bittiming_const = &mpfs_can_bit_timing_data_range; + + priv1->can.can_stats.arbitration_lost = 0; + priv1->can.can_stats.bus_error = 0; + priv1->can.can_stats.bus_off = 0; + priv1->can.can_stats.error_warning = 0; + priv1->can.can_stats.error_passive = 0; + priv1->can.can_stats.restarts = 0; + + /* Get the can_clk info */ + + priv1->can.clock.freq = MPFS_FPGA_PERIPHERAL_CLK; + + /* Needed for timing adjustment to be performed as soon as possible */ + + priv1->can.bittiming.bitrate = CONFIG_MPFS_CANFD_ARBI_BITRATE1; + priv1->can.data_bittiming.bitrate = CONFIG_MPFS_CANFD_DATA_BITRATE1; + priv1->can.bittiming.sjw = 5; + priv1->can.data_bittiming.sjw = 5; + + /* Calculate nominal and data bit timing */ + + mpfs_can_btr_compute(priv1, + &priv1->can.bittiming, + priv1->can.bittiming_const); + mpfs_can_btr_compute(priv1, + &priv1->can.data_bittiming, + priv1->can.data_bittiming_const); + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + /* Init hw filter runtime var */ + + priv1->used_bit_filter_number = 0; + priv1->used_range_filter = false; +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + + /* Set CAN control modes */ + + priv1->can.ctrlmode = CAN_CTRLMODE_FD + | CAN_CTRLMODE_BERR_REPORTING; + + /* Attach the interrupt handler */ + + if (irq_attach(priv1->config->canfd_fpga_irq, mpfs_interrupt, priv1)) + { + /* We could not attach the ISR to the interrupt */ + + canerr("ERROR: Failed to attach to CAN1 IRQ\n"); + return -EAGAIN; + } + + /* Initialize TX/RX descriptor structure */ + + priv1->txdesc = (struct canfd_frame *)&g_tx_pool1; + priv1->rxdesc = (struct canfd_frame *)&g_rx_pool1; + + /* Initialize the driver network device structure */ + + priv1->dev.d_ifup = mpfs_ifup; /* I/F up (new IP address) callback */ + priv1->dev.d_ifdown = mpfs_ifdown; /* I/F down callback */ + priv1->dev.d_txavail = mpfs_txavail; /* New TX data callback */ +#ifdef CONFIG_NETDEV_IOCTL + priv1->dev.d_ioctl = mpfs_ioctl; /* Support CAN ioctl() calls */ +#endif + priv1->dev.d_private = priv1; /* Used to recover private state from dev */ + + /* Reset controller */ + + if (mpfs_reset(priv1) < 0) + { + return -1; + } + + caninfo("CANFD1 driver init done\n"); + + /* Put the interface in the down state. This usually amounts to resetting + * the device and/or calling mpfs_ifdown(). + */ + + mpfs_ifdown(&priv1->dev); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + netdev_register(&priv1->dev, NET_LL_CAN); +#endif /* CONFIG_MPFS_CANFD1 */ + + return OK; +} diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h new file mode 100644 index 0000000000000..9bc78552b3eb7 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h @@ -0,0 +1,87 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_fpga_canfd.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_FPGA_CANFD_H +#define __ARCH_RISCV_SRC_MPFS_MPFS_FPGA_CANFD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Check if CAN-FD support is enabled. */ + +#ifdef CONFIG_MPFS_HAVE_CANFD + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_fpga_canfd_init + * + * Description: + * Initialize a CANFD block. + * + * Returned Value: + * OK on success, Negated errno on failure + * + ****************************************************************************/ + +int mpfs_fpga_canfd_init(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_MPFS_HAVE_CANFD */ +#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_FPGA_CANFD_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c index 26fa4408eb14e..cf0ecd418aa9f 100644 --- a/arch/risc-v/src/mpfs/mpfs_i2c.c +++ b/arch/risc-v/src/mpfs/mpfs_i2c.c @@ -83,7 +83,10 @@ typedef enum mpfs_i2c_status MPFS_I2C_SUCCESS = 0u, MPFS_I2C_IN_PROGRESS, MPFS_I2C_FAILED, - MPFS_I2C_TIMED_OUT + MPFS_I2C_FAILED_SLAW_NACK, + MPFS_I2C_FAILED_SLAR_NACK, + MPFS_I2C_FAILED_TX_DATA_NACK, + MPFS_I2C_FAILED_BUS_ERROR, } mpfs_i2c_status_t; typedef enum mpfs_i2c_clock_divider @@ -123,6 +126,8 @@ static const uint32_t mpfs_i2c_freqs_fpga[MPFS_I2C_NUMBER_OF_DIVIDERS] = MPFS_FPGA_BCLK / 8 }; +static int mpfs_i2c_irq(int cpuint, void *context, void *arg); + static int mpfs_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgs, int count); @@ -298,8 +303,67 @@ static uint32_t mpfs_i2c_timeout(int msgc, struct i2c_msg_s *msgv); static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv) { + int ret = OK; + uint32_t ctrl; + uint32_t status; + if (!priv->initialized) { + /* In case of warm boot, or after reset, check that the IP block is + * not already active and try to recover from any pending data + * transfer if it is. + */ + + ctrl = getreg32(MPFS_I2C_CTRL); + if (ctrl != 0) + { + /* Check if the IP is enabled */ + + status = getreg32(MPFS_I2C_STATUS); + if (ctrl & MPFS_I2C_CTRL_ENS1_MASK) + { + if (status == MPFS_I2C_ST_RX_DATA_ACK) + { + /* In case the machine was in the middle of data RX, try to + * receive one byte and nack it + */ + + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_AA_MASK, 0); + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0); + usleep(100); + status = getreg32(MPFS_I2C_STATUS); + } + + if (status != MPFS_I2C_ST_IDLE) + { + /* If the bus is not idle, send STOP */ + + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0); + modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK); + usleep(100); + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0); + status = getreg32(MPFS_I2C_STATUS); + } + } + + if (status != MPFS_I2C_ST_IDLE) + { + i2cerr("Bus not idle before init\n"); + } + + /* Disable IP and continue initialization */ + + putreg32(0, MPFS_I2C_CTRL); + } + + /* Attach interrupt */ + + ret = irq_attach(priv->plic_irq, mpfs_i2c_irq, priv); + if (ret != OK) + { + return ret; + } + if (priv->fpga) { /* FIC3 is used by many, don't reset it here, or many @@ -358,10 +422,9 @@ static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv) putreg32(priv->ser_address, MPFS_I2C_ADDR); - /* Enable i2c bus */ + /* Enable i2c bus, clear all other bits */ - modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_ENS1_MASK, - MPFS_I2C_CTRL_ENS1_MASK); + putreg32(MPFS_I2C_CTRL_ENS1_MASK, MPFS_I2C_CTRL); priv->initialized = true; } @@ -385,8 +448,7 @@ static void mpfs_i2c_deinit(struct mpfs_i2c_priv_s *priv) up_disable_irq(priv->plic_irq); irq_detach(priv->plic_irq); - modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_ENS1_MASK, - ~MPFS_I2C_CTRL_ENS1_MASK); + putreg32(0, MPFS_I2C_CTRL); priv->initialized = false; } @@ -437,8 +499,6 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) volatile uint32_t status; uint8_t clear_irq = 1u; - DEBUGASSERT(msg != NULL); - status = getreg32(MPFS_I2C_STATUS); switch (status) @@ -472,14 +532,23 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) case MPFS_I2C_ST_SLAW_NACK: modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK); - priv->status = MPFS_I2C_FAILED; + priv->status = MPFS_I2C_FAILED_SLAW_NACK; break; case MPFS_I2C_ST_SLAW_ACK: case MPFS_I2C_ST_TX_DATA_ACK: if (priv->tx_idx < priv->tx_size) { - DEBUGASSERT(priv->tx_buffer != NULL); + if (priv->tx_buffer == NULL) + { + i2cerr("ERROR: tx_buffer is NULL!\n"); + + /* Clear the serial interrupt flag and exit */ + + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0); + return 0; + } + putreg32(priv->tx_buffer[priv->tx_idx], MPFS_I2C_DATA); priv->tx_idx++; } @@ -493,7 +562,10 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) /* Jump to the next message */ - priv->msgid++; + if (priv->msgid < (priv->msgc - 1)) + { + priv->msgid++; + } } else { @@ -512,7 +584,10 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) /* Jump to the next message */ - priv->msgid++; + if (priv->msgid < (priv->msgc - 1)) + { + priv->msgid++; + } } else { @@ -525,7 +600,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) case MPFS_I2C_ST_TX_DATA_NACK: modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK); - priv->status = MPFS_I2C_FAILED; + priv->status = MPFS_I2C_FAILED_TX_DATA_NACK; break; case MPFS_I2C_ST_SLAR_ACK: /* SLA+R tx'ed. */ @@ -547,14 +622,22 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) case MPFS_I2C_ST_SLAR_NACK: /* SLA+R tx'ed; send a stop condition */ modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK); - priv->status = MPFS_I2C_FAILED; + priv->status = MPFS_I2C_FAILED_SLAR_NACK; break; case MPFS_I2C_ST_RX_DATA_ACK: + if (priv->rx_buffer == NULL) + { + i2cerr("ERROR: rx_buffer is NULL!\n"); + + /* Clear the serial interrupt flag and exit */ + + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0); + return 0; + } /* Data byte received, ACK returned */ - DEBUGASSERT(priv->rx_buffer != NULL); priv->rx_buffer[priv->rx_idx] = (uint8_t)getreg32(MPFS_I2C_DATA); priv->rx_idx++; @@ -566,13 +649,31 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) case MPFS_I2C_ST_RX_DATA_NACK: + /* Some sanity checks */ + + if (priv->rx_buffer == NULL) + { + i2cerr("ERROR: rx_buffer is NULL!\n"); + + /* Clear the serial interrupt flag and exit */ + + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0); + return 0; + } + else if (priv->rx_idx >= priv->rx_size) + { + i2cerr("ERROR: rx_idx is out of bounds!\n"); + + /* Clear the serial interrupt flag and exit */ + + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0); + return 0; + } + /* Data byte received, NACK returned */ - DEBUGASSERT(priv->rx_buffer != NULL); - DEBUGASSERT(priv->rx_idx < priv->rx_size); priv->rx_buffer[priv->rx_idx] = (uint8_t)getreg32(MPFS_I2C_DATA); priv->rx_idx++; - priv->status = MPFS_I2C_SUCCESS; modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK); break; @@ -613,7 +714,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) if (priv->status == MPFS_I2C_IN_PROGRESS) { - priv->status = MPFS_I2C_FAILED; + priv->status = MPFS_I2C_FAILED_BUS_ERROR; } break; @@ -665,9 +766,17 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, { struct mpfs_i2c_priv_s *priv = (struct mpfs_i2c_priv_s *)dev; int ret = OK; +#ifdef CONFIG_DEBUG_I2C_ERROR + int sval; + uint32_t status; +#endif i2cinfo("Starting transfer request of %d message(s):\n", count); - DEBUGASSERT(count > 0); + + if (count <= 0) + { + return -EINVAL; + } ret = nxmutex_lock(&priv->lock); if (ret < 0) @@ -675,6 +784,24 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, return ret; } +#ifdef CONFIG_DEBUG_I2C_ERROR + /* We should never start at transfer with semaphore already signalled */ + + sem_getvalue(&priv->sem_isr, &sval); + if (sval != 0) + { + i2cerr("Already signalled at start? %d\n", sval); + } + + /* We should always be idle before transfer */ + + status = getreg32(MPFS_I2C_STATUS); + if (status != MPFS_I2C_ST_IDLE) + { + i2cerr("I2C bus not idle before transfer! Status: 0x%x\n", status); + } +#endif + priv->msgv = msgs; priv->msgc = count; @@ -709,9 +836,17 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, if (msgs[i].flags & I2C_M_NOSTOP) { - /* Support only write + read combinations */ + /* Support only write + read combinations. No write + write, + * nor read + write without stop condition between supported + * yet. + */ - DEBUGASSERT(!(msgs[i].flags & I2C_M_READ)); + if (msgs[i].flags & I2C_M_READ) + { + i2cerr("No read before write supported!\n"); + nxmutex_unlock(&priv->lock); + return -EINVAL; + } /* Combine write + read transaction into one */ @@ -759,6 +894,20 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, i2cinfo("Message %" PRIu8 " transfer complete.\n", priv->msgid); } +#ifdef CONFIG_DEBUG_I2C_ERROR + /* We should always be idle after the transfers */ + + status = getreg32(MPFS_I2C_STATUS); + if (status != MPFS_I2C_ST_IDLE) + { + i2cerr("I2C bus not idle after transfer! Status: 0x%x\n", status); + } +#endif + + /* Irq was enabled at mpfs_i2c_sendstart() */ + + up_disable_irq(priv->plic_irq); + nxmutex_unlock(&priv->lock); return ret; } @@ -782,26 +931,15 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev) { struct mpfs_i2c_priv_s *priv = (struct mpfs_i2c_priv_s *)dev; int ret; - irqstate_t flags; - DEBUGASSERT(priv != NULL); - - flags = enter_critical_section(); - - /* Disabling I2C interrupts. - * NOTE: up_enable_irq() will be called at mpfs_i2c_sendstart() - */ - - up_disable_irq(priv->plic_irq); + nxmutex_lock(&priv->lock); - priv->inflight = false; - priv->status = MPFS_I2C_SUCCESS; - priv->initialized = false; + mpfs_i2c_deinit(priv); ret = mpfs_i2c_init(priv); if (ret != OK) { - leave_critical_section(flags); + nxmutex_unlock(&priv->lock); return ret; } @@ -809,8 +947,10 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev) priv->tx_idx = 0; priv->rx_size = 0; priv->rx_idx = 0; + priv->inflight = false; + priv->status = MPFS_I2C_SUCCESS; - leave_critical_section(flags); + nxmutex_unlock(&priv->lock); return OK; } @@ -1004,14 +1144,6 @@ struct i2c_master_s *mpfs_i2cbus_initialize(int port) priv->fpga = true; #endif - ret = irq_attach(priv->plic_irq, mpfs_i2c_irq, priv); - if (ret != OK) - { - priv->refs--; - nxmutex_unlock(&priv->lock); - return NULL; - } - ret = mpfs_i2c_init(priv); if (ret != OK) { diff --git a/arch/risc-v/src/mpfs/mpfs_irq.c b/arch/risc-v/src/mpfs/mpfs_irq.c index a7550c5d7317d..5ee1a744ed8b6 100644 --- a/arch/risc-v/src/mpfs/mpfs_irq.c +++ b/arch/risc-v/src/mpfs/mpfs_irq.c @@ -50,6 +50,18 @@ void up_irqinitialize(void) up_irq_save(); + /* Complete possibly claimed IRQs in PLIC (for current hart) in case + * of warm reboot, e.g. after a crash in the middle of IRQ handler. + * This has no effect on non-claimed or disabled interrupts. + */ + + uintptr_t claim_address = mpfs_plic_get_claimbase(); + + for (int irq = MPFS_IRQ_EXT_START; irq < NR_IRQS; irq++) + { + putreg32(irq - MPFS_IRQ_EXT_START, claim_address); + } + /* Disable all global interrupts for current hart */ uintptr_t iebase = mpfs_plic_get_iebase(); @@ -61,12 +73,6 @@ void up_irqinitialize(void) putreg32(0x0, iebase + 16); putreg32(0x0, iebase + 20); - /* Clear pendings in PLIC (for current hart) */ - - uintptr_t claim_address = mpfs_plic_get_claimbase(); - uint32_t val = getreg32(claim_address); - putreg32(val, claim_address); - /* Colorize the interrupt stack for debug purposes */ #if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 15 @@ -76,9 +82,7 @@ void up_irqinitialize(void) /* Set priority for all global interrupts to 1 (lowest) */ - int id; - - for (id = 1; id <= NR_IRQS; id++) + for (int id = 1; id <= NR_IRQS; id++) { putreg32(1, (uintptr_t)(MPFS_PLIC_PRIORITY + (4 * id))); } diff --git a/arch/risc-v/src/mpfs/mpfs_lowputc.c b/arch/risc-v/src/mpfs/mpfs_lowputc.c index 93dede2fd4ad0..8daa7d6b82f3c 100644 --- a/arch/risc-v/src/mpfs/mpfs_lowputc.c +++ b/arch/risc-v/src/mpfs/mpfs_lowputc.c @@ -40,6 +40,8 @@ ****************************************************************************/ /* Select UART parameters for the selected console */ + +#ifndef CONFIG_MPFS_FPGA_UART #if defined(CONFIG_UART0_SERIAL_CONSOLE) # define MPFS_CONSOLE_BASE MPFS_UART0_BASE # define MPFS_CONSOLE_BAUD CONFIG_UART0_BAUD @@ -89,6 +91,93 @@ # error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" # endif +#else /* CONFIG_MPFS_FPGA_UART */ + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART0_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART0_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART0_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART0_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART0_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART1_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART1_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART1_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART1_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART1_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART2_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART2_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART2_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART2_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART2_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART3_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART3_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART3_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART3_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART3_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART4_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART4_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART4_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART4_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART4_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART4_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART5_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART5_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART5_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART5_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART5_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART5_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART6_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART6_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART6_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART6_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART6_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART6_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART7_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART7_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART7_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART7_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART7_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART7_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(HAVE_UART) +# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" +#endif +#endif /* CONFIG_MPFS_FPGA_UART */ + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -111,7 +200,16 @@ static void config_baud_divisors(void) uint32_t fractional_baud_value; uint64_t pclk_freq; - pclk_freq = MPFS_MSS_APB_AHB_CLK; + if (MPFS_CONSOLE_CLOCKBIT == SYSREG_SUBBLK_CLOCK_CR_FIC3) + { + /* This is an FPGA UART */ + + pclk_freq = MPFS_FPGA_PERIPHERAL_CLK; + } + else + { + pclk_freq = MPFS_MSS_APB_AHB_CLK; + } /* Compute baud value based on requested baud rate and PCLK frequency. * The baud value is computed using the following equation: @@ -189,20 +287,23 @@ void mpfs_lowsetup(void) #if defined(HAVE_SERIAL_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) uint32_t lcr = 0; - /* reset on */ + /* reset on - only for non-FPGA uarts */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, - 0, MPFS_CONSOLE_RESETBIT); + if (SYSREG_SUBBLK_CLOCK_CR_FIC3 != MPFS_CONSOLE_CLOCKBIT) + { + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, 0, + MPFS_CONSOLE_RESETBIT); + } /* reset off */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, - 0, MPFS_CONSOLE_CLOCKBIT); + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, + MPFS_CONSOLE_RESETBIT, 0); /* clock on */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, - MPFS_CONSOLE_RESETBIT, 0); + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, + 0, MPFS_CONSOLE_CLOCKBIT); switch (MPFS_CONSOLE_BITS) { diff --git a/arch/risc-v/src/mpfs/mpfs_mm_init.c b/arch/risc-v/src/mpfs/mpfs_mm_init.c index 90f69b33fe440..6c5bdd394dacc 100644 --- a/arch/risc-v/src/mpfs/mpfs_mm_init.c +++ b/arch/risc-v/src/mpfs/mpfs_mm_init.c @@ -54,9 +54,9 @@ #define PGT_L2_VBASE PGT_L2_PBASE #define PGT_L3_VBASE PGT_L3_PBASE -#define PGT_L1_SIZE (512) /* Enough to map 512 GiB */ -#define PGT_L2_SIZE (512) /* Enough to map 1 GiB */ -#define PGT_L3_SIZE (1024) /* Enough to map 4 MiB */ +#define PGT_L1_SIZE (512) /* Enough to map 512 GiB */ +#define PGT_L2_SIZE (512) /* Enough to map 1 GiB */ +#define PGT_L3_SIZE (40 * 1024) /* Enough to map 40 MiB */ /* Calculate the minimum size for the L3 table */ @@ -251,4 +251,9 @@ void mpfs_kernel_mappings(void) mmu_ln_map_region(2, PGT_L2_VBASE, PGPOOL_START, PGPOOL_START, PGPOOL_SIZE, MMU_KDATA_FLAGS); + + /* Map the MTIME counter to the start of USR IO region */ + + map_region(MPFS_CLINT_MTIME & (~RV_MMU_PAGE_MASK), USRIO_START, + RV_MMU_PAGE_SIZE, PTE_R | PTE_U | PTE_G); } diff --git a/arch/risc-v/src/mpfs/mpfs_mpu.c b/arch/risc-v/src/mpfs/mpfs_mpu.c new file mode 100644 index 0000000000000..2643c79c0ac7a --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_mpu.c @@ -0,0 +1,283 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_mpu.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include + +#include "riscv_internal.h" +#include "mpfs_memorymap.h" + +#include "hardware/mpfs_mpucfg.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* MPUCFG entry is 64-bits */ + +#define MPFS_MPUCFG_WIDTH 64 + +/* Mode bits [63:56] */ + +#define MPFS_MPUCFG_MODE_SHIFT 56 +#define MPFS_MPUCFG_MODE_WIDTH 8 +#define MPFS_MPUCFG_MODE_MASK \ + (((1ul << MPFS_MPUCFG_MODE_WIDTH) - 1) << MPFS_MPUCFG_MODE_SHIFT) + +/* PMP entry bits [35:0] */ + +#define MPFS_MPUCFG_PMP_SHIFT 0 +#define MPFS_MPUCFG_PMP_WIDTH 36 +#define MPFS_MPUCFG_PMP_MASK \ + (((1ul << MPFS_MPUCFG_PMP_WIDTH) - 1) << MPFS_MPUCFG_PMP_SHIFT) + +/* Encode the MPUCFG register value */ + +#define MPFS_MPUCFG_ENCODE(mode, napot) \ + ((((mode) << MPFS_MPUCFG_MODE_SHIFT) & MPFS_MPUCFG_MODE_MASK) | \ + (((napot) << MPFS_MPUCFG_PMP_SHIFT) & MPFS_MPUCFG_PMP_MASK)) + +/* Decode the MPUCFG register value */ + +#define MPFS_MPUCFG_DECODE(reg, mode, napot) \ + do \ + { \ + uintptr_t val = getreg64(reg); \ + *(mode) = (val & MPFS_MPUCFG_MODE_MASK) >> MPFS_MPUCFG_MODE_SHIFT; \ + *(napot) = (val & MPFS_MPUCFG_PMP_MASK) >> MPFS_MPUCFG_PMP_SHIFT; \ + } \ + while(0) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: napot_decode + * + * Description: + * Decode base and size from NAPOT value + * + * Input Parameters: + * val - Value to decode. + * size - Size out. + * + * Returned Value: + * Base address. + * + ****************************************************************************/ + +static void napot_decode(uintptr_t val, uintptr_t *base, uintptr_t *size) +{ + uintptr_t mask = (uintptr_t)(-1) >> 1; + uintptr_t pot = MPFS_MPUCFG_WIDTH + 2; + + while (mask) + { + if ((val & mask) == mask) + { + break; + } + + pot--; + mask >>= 1; + } + + *size = UINT64_C(1) << pot; + *base = (val & ~mask) << 2; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_mpu_set + * + * Description: + * Set value to MPFS MPUCFG register. + * + * Input Parameters: + * reg - The MPUCFG register to write. + * perm - The region permissions. + * base - The base address of the region. + * size - The length of the region. + * + * Note: + * Only NAPOT encoded regions are supported, thus the base address and + * size must align with each other. + * + * Returned Value: + * 0 on success; negated error on failure. + * + ****************************************************************************/ + +int mpfs_mpu_set(uintptr_t reg, uintptr_t perm, uintptr_t base, + uintptr_t size) +{ + uintptr_t mode; + uintptr_t napot; + + /* Read the the permission and napot fields */ + + MPFS_MPUCFG_DECODE(reg, &mode, &napot); + + /* First, check that the register is not already configured */ + + if ((mode & PMPCFG_L) != 0) + { + /* The entry is locked, get out */ + + return -EACCES; + } + + /* Base must be word aligned, minimum size is 4K */ + + if ((base & 0x07) != 0 || size < 0x1000) + { + return -EINVAL; + } + + /* Make sure the base + size are NAPOT encodable */ + + if ((base & ((UINT64_C(1) << log2ceil(size)) - 1)) != 0) + { + /* The start address is not properly aligned with size */ + + return -EINVAL; + } + + /* Sanity check the register */ + + if (reg < MPFS_MPUCFG_BASE || reg >= MPFS_MPUCFG_END) + { + return -EINVAL; + } + + /* Calculate mode (RWX), only NAPOT encoding is supported */ + + mode = (perm & (PMPCFG_RWX_MASK | PMPCFG_L)) | PMPCFG_A_NAPOT; + + /* Do the NAPOT encoding */ + + napot = (base >> 2) | ((size - 1) >> 3); + + /* Then set the value */ + + putreg64(MPFS_MPUCFG_ENCODE(mode, napot), reg); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_mpu_access_ok + * + * Description: + * Check if MPFS MPUCFG access is OK for register. + * + * Input Parameters: + * reg - The MPUCFG register to check. + * perm - The region permissions. + * base - The base address of the region. + * size - The length of the region. + * + * Returned Value: + * true if access OK; false if not. + * + ****************************************************************************/ + +bool mpfs_mpu_access_ok(uintptr_t reg, uintptr_t perm, uintptr_t base, + uintptr_t size) +{ + uintptr_t mode; + uintptr_t napot; + uintptr_t reg_base; + uintptr_t reg_size; + + /* Read the the permission and napot fields */ + + MPFS_MPUCFG_DECODE(reg, &mode, &napot); + + /* Check for permission match */ + + if ((mode & PMPCFG_RWX_MASK) != perm) + { + return false; + } + + /* Decode the napot field */ + + napot_decode(napot, ®_base, ®_size); + + /* Then check if the area fits */ + + return (base >= reg_base && (base + size) <= (reg_base + reg_size)); +} + +/**************************************************************************** + * Name: mpfs_mpu_lock + * + * Description: + * Lock an MPUCFG register from further modifications. + * + * Input Parameters: + * reg - The MPUCFG register to lock. + * + * Returned Value: + * 0 on success; negated error on failure. + * + ****************************************************************************/ + +int mpfs_mpu_lock(uintptr_t reg) +{ + uintptr_t mode; + uintptr_t napot; + + /* Sanity check the register */ + + if (reg < MPFS_MPUCFG_BASE || reg >= MPFS_MPUCFG_END) + { + return -EINVAL; + } + + MPFS_MPUCFG_DECODE(reg, &mode, &napot); + + /* If the entry is already locked, everything is fine */ + + if ((mode & PMPCFG_L) == 0) + { + /* Set the lock bit and write the value back */ + + putreg64(MPFS_MPUCFG_ENCODE(mode | PMPCFG_L, napot), reg); + } + + return OK; +} diff --git a/arch/risc-v/src/mpfs/mpfs_mpu.h b/arch/risc-v/src/mpfs/mpfs_mpu.h new file mode 100644 index 0000000000000..d934cd64044ef --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_mpu.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_mpu.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISC_V_SRC_MPFS_MPFS_MPU_H +#define __ARCH_RISC_V_SRC_MPFS_MPFS_MPU_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_mpu_set + * + * Description: + * Set value to MPFS MPUCFG register. + * + * Input Parameters: + * reg - The MPUCFG register to write. + * perm - The region permissions. + * base - The base address of the region. + * size - The length of the region. + * + * Note: + * Only NAPOT encoded regions are supported, thus the base address and + * size must align with each other. + * + * Returned Value: + * 0 on success; negated error on failure. + * + ****************************************************************************/ + +int mpfs_mpu_set(uintptr_t reg, uintptr_t perm, uintptr_t base, + uintptr_t size); + +/**************************************************************************** + * Name: mpfs_mpu_access_ok + * + * Description: + * Check if MPFS MPUCFG access is OK for register. + * + * Input Parameters: + * reg - The MPUCFG register to check. + * perm - The region permissions. + * base - The base address of the region. + * size - The length of the region. + * + * Returned Value: + * true if access OK; false if not. + * + ****************************************************************************/ + +bool mpfs_mpu_access_ok(uintptr_t reg, uintptr_t perm, uintptr_t base, + uintptr_t size); + +/**************************************************************************** + * Name: mpfs_mpu_lock + * + * Description: + * Lock an MPUCFG register from further modifications. + * + * Input Parameters: + * reg - The MPUCFG register to lock. + * + * Returned Value: + * 0 on success; negated error on failure. + * + ****************************************************************************/ + +int mpfs_mpu_lock(uintptr_t reg); + +#endif /* __ARCH_RISC_V_SRC_MPFS_MPFS_MPU_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi.c b/arch/risc-v/src/mpfs/mpfs_opensbi.c index ad9e835c346c5..77f14d127e189 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi.c +++ b/arch/risc-v/src/mpfs/mpfs_opensbi.c @@ -28,8 +28,31 @@ #include #ifdef CONFIG_MPFS_IHC_SBI #include +#include +#endif +#include "mpfs_entrypoints.h" + +/* Make sure that anything that intefraces with the SBI uses the same data + * types as the SBI code (e.g. same "bool") + */ + +#ifdef bool +#undef bool +#endif + +#ifdef true +#undef true +#endif + +#ifdef false +#undef false #endif +#ifdef NULL +#undef NULL +#endif + +#include #include #include #include @@ -41,10 +64,6 @@ #include #include -#ifdef CONFIG_MPFS_IHC_SBI -#include -#endif - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -184,30 +203,7 @@ static struct aclint_mswi_data mpfs_mswi = * Unused hart is marked with -1. Mpfs will always have the hart0 unused. */ -static const u32 mpfs_hart_index2id[MPFS_HART_COUNT] = -{ - [0] = -1, -#ifdef CONFIG_MPFS_HART1_SBI - [1] = 1, -#else - [1] = -1, -#endif -#ifdef CONFIG_MPFS_HART2_SBI - [2] = 2, -#else - [2] = -1, -#endif -#ifdef CONFIG_MPFS_HART3_SBI - [3] = 3, -#else - [3] = -1, -#endif -#ifdef CONFIG_MPFS_HART4_SBI - [4] = 4, -#else - [4] = -1, -#endif -}; +static u32 mpfs_hart_index2id[MPFS_HART_COUNT]; static const struct sbi_platform platform = { @@ -602,6 +598,13 @@ static int mpfs_opensbi_ecall_handler(long funcid, void __attribute__((noreturn)) mpfs_opensbi_setup(void) { uint32_t hartid = current_hartid(); + size_t i; + + for (i = 0; i < sizeof(mpfs_hart_index2id) / sizeof(mpfs_hart_index2id[0]); + i++) + { + mpfs_hart_index2id[i] = mpfs_get_use_sbi(i) ? i : -1; + } sbi_console_set_device(&mpfs_console); mpfs_opensbi_scratch_setup(hartid); diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S b/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S index 517cc20dc9814..eab2ecb06280c 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S +++ b/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S @@ -167,8 +167,10 @@ mpfs_global_pointer: /* Restore GP */ - la a0, mpfs_global_pointer - ld gp, 0(a0) + .option push + .option norelax + la gp, __global_pointer$ + .option pop /* Call C routine */ diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S b/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S index db8f8fff7f738..6f623ed560def 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S +++ b/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S @@ -39,6 +39,22 @@ ****************************************************************************/ .global mpfs_opensbi_prepare_hart + .global mpfs_opensbi_relocate_from_envm + + /* Add some weak default values to make this compile without */ + + .weak _sbi_zerodev_loadaddr + .weak _ssbi_zerodev + .weak _esbi_zerodev + + /* These are the weak pointless variables, only to get this PR compile */ + +_sbi_zerodev_loadaddr: + .dword 0x0a006000 +_ssbi_zerodev: + .dword _stext +_esbi_zerodev: + .dword _stext /**************************************************************************** * Private Data @@ -68,21 +84,43 @@ mpfs_global_pointer: * ****************************************************************************/ + .align 3 +mpfs_opensbi_relocate_from_envm: + + /* Relocate the code from eNVM into L2 zero device */ + + la a0, _sbi_zerodev_loadaddr + la a1, _ssbi_zerodev + la a2, _esbi_zerodev +.check_if_opensbi_copy_done: + bge a1, a2, .opensbi_copy_done + ld a3, 0(a0) + sd a3, 0(a1) + addi a0, a0, 8 + addi a1, a1, 8 + j .check_if_opensbi_copy_done +.opensbi_copy_done: + + /* To make a store to instruction memory visible to all RISC-V harts, the + * writing hart has to execute a data FENCE before requesting that all + * remote RISC-V harts execute a FENCE.I. This is hart0 only. + */ + + fence + ret + .align 3 mpfs_opensbi_prepare_hart: + /* These are harts other than 0. Thus, fence.i */ + + fence.i + /* Setup OpenSBI exception handler */ la t0, mpfs_exception_opensbi csrw mtvec, t0 - /* la gp, __global_pointer$ will not work. We want to have the gp as seen - * in the .map file exactly. We need to restore gp in the trap handler. - */ - - la t0, mpfs_global_pointer - ld gp, 0(t0) - /* Setup stacks per hart, the stack top is the end of the hart's scratch */ csrr a0, mhartid diff --git a/arch/risc-v/src/mpfs/mpfs_sdio.c b/arch/risc-v/src/mpfs/mpfs_sdio.c new file mode 100644 index 0000000000000..530ae37e659ab --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_sdio.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_sdio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mpfs_coremmc.h" +#include "mpfs_emmcsd.h" +#include "mpfs_sdio_dev.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sdio_initialize + * + * Description: + * Initialize SDIO for operation. + * + * Input Parameters: + * slotno - Not used. + * + * Returned Values: + * A reference to an SDIO interface structure. NULL is returned on + * failures. + * + ****************************************************************************/ + +struct sdio_dev_s *sdio_initialize(int slotno) +{ + switch (slotno) + { + case 0: +#ifdef CONFIG_MPFS_EMMCSD + return mpfs_emmcsd_sdio_initialize(slotno); +#endif + + case 1: +#ifdef CONFIG_MPFS_COREMMC + return mpfs_coremmc_sdio_initialize(slotno); +#endif + + default: + break; + } + + mcerr("sdio slot number %d not supported!\n", slotno); + return NULL; +} + +/**************************************************************************** + * Name: sdio_mediachange + * + * Description: + * Called by board-specific logic -- possible from an interrupt handler -- + * in order to signal to the driver that a card has been inserted or + * removed from the slot + * + * Input Parameters: + * dev - An instance of the SDIO driver device state structure. + * cardinslot - true is a card has been detected in the slot; false if a + * card has been removed from the slot. Only transitions + * (inserted->removed or removed->inserted should be reported) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot) +{ + struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev; + + if (!dev) + { + mcerr("sdio device not found\n"); + return; + } + + switch (priv->hw_base) + { +#ifdef CONFIG_MPFS_EMMCSD + case MPFS_EMMC_SD_BASE: + mpfs_emmcsd_sdio_mediachange(dev, cardinslot); + return; +#endif + +#ifdef CONFIG_MPFS_COREMMC + case CONFIG_MPFS_COREMMC_BASE: + mpfs_coremmc_sdio_mediachange(dev, cardinslot); + return; +#endif + + default: + break; + } + + mcerr("Invalid sdio base address\n"); +} + +/**************************************************************************** + * Name: sdio_wrprotect + * + * Description: + * Called by board-specific logic to report if the card in the slot is + * mechanically write protected. + * + * Input Parameters: + * dev - An instance of the SDIO driver device state structure. + * wrprotect - true is a card is writeprotected. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect) +{ + struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev; + + if (!dev) + { + mcerr("sdio device not found\n"); + return; + } + + switch (priv->hw_base) + { +#ifdef CONFIG_MPFS_EMMCSD + case MPFS_EMMC_SD_BASE: + mpfs_emmcsd_sdio_wrprotect(dev, wrprotect); + return; +#endif + +#ifdef CONFIG_MPFS_COREMMC + case CONFIG_MPFS_COREMMC_BASE: + mpfs_coremmc_sdio_wrprotect(dev, wrprotect); + return; +#endif + + default: + break; + } + + mcerr("Invalid sdio base address\n"); +} diff --git a/arch/risc-v/src/mpfs/mpfs_sdio.h b/arch/risc-v/src/mpfs/mpfs_sdio.h new file mode 100644 index 0000000000000..ec63db76e7c3c --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_sdio.h @@ -0,0 +1,112 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_sdio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_SDIO_H +#define __ARCH_RISCV_SRC_MPFS_MPFS_SDIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "chip.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: sdio_initialize + * + * Description: + * Initialize SDIO for operation. + * + * Input Parameters: + * slotno - Not used. + * + * Returned Values: + * A reference to an SDIO interface structure. NULL is returned on + * failures. + * + ****************************************************************************/ + +struct sdio_dev_s; /* See include/nuttx/sdio.h */ +struct sdio_dev_s *sdio_initialize(int slotno); + +/**************************************************************************** + * Name: sdio_mediachange + * + * Description: + * Called by board-specific logic -- possibly from an interrupt handler -- + * in order to signal to the driver that a card has been inserted or + * removed from the slot. + * + * Input Parameters: + * dev - An instance of the SDIO driver device state structure. + * cardinslot - true is a card has been detected in the slot; false if a + * card has been removed from the slot. Only transitions + * (inserted->removed or removed->inserted should be reported) + * + * Returned Values: + * None + * + ****************************************************************************/ + +void sdio_mediachange(struct sdio_dev_s *dev, bool cardinslot); + +/**************************************************************************** + * Name: sdio_wrprotect + * + * Description: + * Called by board-specific logic to report if the card in the slot is + * mechanically write protected. + * + * Input Parameters: + * dev - An instance of the SDIO driver device state structure. + * wrprotect - true is a card is writeprotected. + * + * Returned Values: + * None + * + ****************************************************************************/ + +void sdio_wrprotect(struct sdio_dev_s *dev, bool wrprotect); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_SDIO_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_sdio_dev.h b/arch/risc-v/src/mpfs/mpfs_sdio_dev.h new file mode 100644 index 0000000000000..688a6c462756d --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_sdio_dev.h @@ -0,0 +1,92 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_sdio_dev.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_SDIO_DEV_H +#define __ARCH_RISCV_SRC_MPFS_MPFS_SDIO_DEV_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure defines the state of the MPFS eMMCSD interface */ + +struct mpfs_dev_s +{ + struct sdio_dev_s dev; /* Standard, base SDIO interface */ + + const uintptr_t hw_base; /* Base address */ + const int plic_irq; /* PLIC interrupt */ + bool clk_enabled; /* Clk state */ + + /* eMMC / SD and HW parameters */ + + const bool emmc; /* eMMC or SD */ + int bus_voltage; /* Bus voltage */ + int bus_mode; /* eMMC Bus mode */ + bool jumpers_3v3; /* Jumper settings: 1v8 or 3v3 */ + + /* Event support */ + + sem_t waitsem; /* Implements event waiting */ + sdio_eventset_t waitevents; /* Set of events to be waited for */ + uint32_t waitmask; /* Interrupt enables for event waiting */ + volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */ + struct wdog_s waitwdog; /* Watchdog that handles event timeouts */ + + /* Callback support */ + + sdio_statset_t cdstatus; /* Card status */ + sdio_eventset_t cbevents; /* Set of events to be cause callbacks */ + worker_t callback; /* Registered callback function */ + void *cbarg; /* Registered callback argument */ + struct work_s cbwork; /* Callback work queue structure */ + + /* Interrupt mode data transfer support */ + + uint32_t *buffer; /* Address of current R/W buffer */ + size_t remaining; /* Number of bytes remaining in the transfer */ + size_t receivecnt; /* Real count to receive */ + uint32_t xfrmask; /* Interrupt enables for data transfer */ + uint32_t xfr_blkmask; /* Interrupt enables for SB/MB data transfer */ + + bool widebus; /* Required for DMA support */ + bool onebit; /* true: Only 1-bit transfers are supported */ + + /* DMA data transfer support */ + + bool polltransfer; /* Indicate a poll transfer, no DMA */ + bool multiblock; /* Indicate a multi-block transfer */ + + /* Misc */ + + uint32_t blocksize; /* Current block size */ + uint32_t fifo_depth; /* Fifo size, read from the register */ +}; + +#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_SDIO_DEV_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_serial.c b/arch/risc-v/src/mpfs/mpfs_serial.c index ec9ab908cf712..9064a1f060c4d 100644 --- a/arch/risc-v/src/mpfs/mpfs_serial.c +++ b/arch/risc-v/src/mpfs/mpfs_serial.c @@ -80,6 +80,15 @@ # elif defined(CONFIG_UART4_SERIAL_CONSOLE) # define CONSOLE_DEV g_uart4port /* UART4 is console */ # define SERIAL_CONSOLE 5 +# elif defined(CONFIG_UART5_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart5port /* UART5 is console */ +# define SERIAL_CONSOLE 6 +# elif defined(CONFIG_UART6_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart6port /* UART6 is console */ +# define SERIAL_CONSOLE 7 +# elif defined(CONFIG_UART7_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart7port /* UART7 is console */ +# define SERIAL_CONSOLE 8 # else # error "I'm confused... Do we have a serial console or not?" # endif @@ -90,6 +99,9 @@ # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # if defined(CONFIG_MPFS_UART0) # define SERIAL_CONSOLE 1 # elif defined(CONFIG_MPFS_UART1) @@ -100,6 +112,12 @@ # define SERIAL_CONSOLE 4 # elif defined(CONFIG_MPFS_UART4) # define SERIAL_CONSOLE 5 +# elif defined(CONFIG_MPFS_UART5) +# define SERIAL_CONSOLE 6 +# elif defined(CONFIG_MPFS_UART6) +# define SERIAL_CONSOLE 7 +# elif defined(CONFIG_MPFS_UART7) +# define SERIAL_CONSOLE 8 # else # undef TTYS0_DEV # undef TTYS1_DEV @@ -127,6 +145,7 @@ struct up_dev_s uint8_t parity; /* 0=none, 1=odd, 2=even */ uint8_t bits; /* Number of bits (7 or 8) */ bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ + bool fpga; /* true: this is an FPGA based driver */ }; /**************************************************************************** @@ -197,6 +216,22 @@ static char g_uart4rxbuffer[CONFIG_UART4_RXBUFSIZE]; static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE]; #endif +#ifdef CONFIG_MPFS_UART5 +static char g_uart5rxbuffer[CONFIG_UART5_RXBUFSIZE]; +static char g_uart5txbuffer[CONFIG_UART5_TXBUFSIZE]; +#endif + +#ifdef CONFIG_MPFS_UART6 +static char g_uart6rxbuffer[CONFIG_UART6_RXBUFSIZE]; +static char g_uart6txbuffer[CONFIG_UART6_TXBUFSIZE]; +#endif + +#ifdef CONFIG_MPFS_UART7 +static char g_uart7rxbuffer[CONFIG_UART7_RXBUFSIZE]; +static char g_uart7txbuffer[CONFIG_UART7_TXBUFSIZE]; +#endif + +#ifndef CONFIG_MPFS_FPGA_UART #ifdef CONFIG_MPFS_UART0 static struct up_dev_s g_uart0priv = { @@ -206,6 +241,7 @@ static struct up_dev_s g_uart0priv = .parity = CONFIG_UART0_PARITY, .bits = CONFIG_UART0_BITS, .stopbits2 = CONFIG_UART0_2STOP, + .fpga = false, }; static uart_dev_t g_uart0port = @@ -237,6 +273,7 @@ static struct up_dev_s g_uart1priv = .parity = CONFIG_UART1_PARITY, .bits = CONFIG_UART1_BITS, .stopbits2 = CONFIG_UART1_2STOP, + .fpga = false, }; static uart_dev_t g_uart1port = @@ -268,6 +305,7 @@ static struct up_dev_s g_uart2priv = .parity = CONFIG_UART2_PARITY, .bits = CONFIG_UART2_BITS, .stopbits2 = CONFIG_UART2_2STOP, + .fpga = false, }; static uart_dev_t g_uart2port = @@ -299,6 +337,7 @@ static struct up_dev_s g_uart3priv = .parity = CONFIG_UART3_PARITY, .bits = CONFIG_UART3_BITS, .stopbits2 = CONFIG_UART3_2STOP, + .fpga = false, }; static uart_dev_t g_uart3port = @@ -330,6 +369,7 @@ static struct up_dev_s g_uart4priv = .parity = CONFIG_UART4_PARITY, .bits = CONFIG_UART4_BITS, .stopbits2 = CONFIG_UART4_2STOP, + .fpga = false, }; static uart_dev_t g_uart4port = @@ -352,6 +392,266 @@ static uart_dev_t g_uart4port = }; #endif +#else /* CONFIG_MPFS_FPGA_UART */ + +#ifdef CONFIG_MPFS_UART0 +static struct up_dev_s g_uart0priv = +{ + .uartbase = MPFS_FPGA_UART0_BASE, + .baud = CONFIG_UART0_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_12, + .parity = CONFIG_UART0_PARITY, + .bits = CONFIG_UART0_BITS, + .stopbits2 = CONFIG_UART0_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart0port = +{ +#if SERIAL_CONSOLE == 1 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART1 +static struct up_dev_s g_uart1priv = +{ + .uartbase = MPFS_FPGA_UART1_BASE, + .baud = CONFIG_UART1_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_13, + .parity = CONFIG_UART1_PARITY, + .bits = CONFIG_UART1_BITS, + .stopbits2 = CONFIG_UART1_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart1port = +{ +#if SERIAL_CONSOLE == 2 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART2 +static struct up_dev_s g_uart2priv = +{ + .uartbase = MPFS_FPGA_UART2_BASE, + .baud = CONFIG_UART2_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_14, + .parity = CONFIG_UART2_PARITY, + .bits = CONFIG_UART2_BITS, + .stopbits2 = CONFIG_UART2_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart2port = +{ +#if SERIAL_CONSOLE == 3 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART2_RXBUFSIZE, + .buffer = g_uart2rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART2_TXBUFSIZE, + .buffer = g_uart2txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart2priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART3 +static struct up_dev_s g_uart3priv = +{ + .uartbase = MPFS_FPGA_UART3_BASE, + .baud = CONFIG_UART3_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_15, + .parity = CONFIG_UART3_PARITY, + .bits = CONFIG_UART3_BITS, + .stopbits2 = CONFIG_UART3_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart3port = +{ +#if SERIAL_CONSOLE == 4 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART3_RXBUFSIZE, + .buffer = g_uart3rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART3_TXBUFSIZE, + .buffer = g_uart3txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart3priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART4 +static struct up_dev_s g_uart4priv = +{ + .uartbase = MPFS_FPGA_UART4_BASE, + .baud = CONFIG_UART4_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_16, + .parity = CONFIG_UART4_PARITY, + .bits = CONFIG_UART4_BITS, + .stopbits2 = CONFIG_UART4_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart4port = +{ +#if SERIAL_CONSOLE == 5 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART4_RXBUFSIZE, + .buffer = g_uart4rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART4_TXBUFSIZE, + .buffer = g_uart4txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart4priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART5 +static struct up_dev_s g_uart5priv = +{ + .uartbase = MPFS_FPGA_UART5_BASE, + .baud = CONFIG_UART5_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_17, + .parity = CONFIG_UART5_PARITY, + .bits = CONFIG_UART5_BITS, + .stopbits2 = CONFIG_UART5_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart5port = +{ +#if SERIAL_CONSOLE == 6 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART5_RXBUFSIZE, + .buffer = g_uart5rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART5_TXBUFSIZE, + .buffer = g_uart5txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart5priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART6 +static struct up_dev_s g_uart6priv = +{ + .uartbase = MPFS_FPGA_UART6_BASE, + .baud = CONFIG_UART6_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_18, + .parity = CONFIG_UART6_PARITY, + .bits = CONFIG_UART6_BITS, + .stopbits2 = CONFIG_UART6_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart6port = +{ +#if SERIAL_CONSOLE == 7 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART6_RXBUFSIZE, + .buffer = g_uart6rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART6_TXBUFSIZE, + .buffer = g_uart6txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart6priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART7 +static struct up_dev_s g_uart7priv = +{ + .uartbase = MPFS_FPGA_UART7_BASE, + .baud = CONFIG_UART7_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_19, + .parity = CONFIG_UART7_PARITY, + .bits = CONFIG_UART7_BITS, + .stopbits2 = CONFIG_UART7_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart7port = +{ +#if SERIAL_CONSOLE == 7 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART7_RXBUFSIZE, + .buffer = g_uart7rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART7_TXBUFSIZE, + .buffer = g_uart7txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart7priv, +}; +#endif + +#endif /* CONFIG_MPFS_FPGA_UART */ + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -447,34 +747,55 @@ static void up_enable_uart(struct up_dev_s *priv, bool enable) clock_bit = SYSREG_SUBBLK_CLOCK_CR_MMUART4; reset_bit = SYSREG_SOFT_RESET_CR_MMUART4; break; + case MPFS_FPGA_UART0_BASE: + case MPFS_FPGA_UART1_BASE: + case MPFS_FPGA_UART2_BASE: + case MPFS_FPGA_UART3_BASE: + case MPFS_FPGA_UART4_BASE: + case MPFS_FPGA_UART5_BASE: + case MPFS_FPGA_UART6_BASE: + case MPFS_FPGA_UART7_BASE: + clock_bit = SYSREG_SUBBLK_CLOCK_CR_FIC3; + reset_bit = SYSREG_SOFT_RESET_CR_FIC3 | SYSREG_SOFT_RESET_CR_FPGA; + break; default: return; } - /* reset on */ + /* reset on for non-fpga */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, - 0, reset_bit); + if (!priv->fpga) + { + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, + 0, reset_bit); + } if (enable) { /* reset off */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, - 0, reset_bit); + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, + reset_bit, 0); /* clock on */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, - clock_bit, 0); + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, + 0, clock_bit); } else { - /* clock off */ + /* clock off for non-fpga */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, - clock_bit, 0); + if (!priv->fpga) + { + /* Turning off FPGA clk would disable it for all other FPGA + * peripherals as well. Don't touch it without refcnt mechanism. + */ + + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, + clock_bit, 0); + } } } @@ -494,7 +815,14 @@ static void up_config_baud_divisors(struct up_dev_s *priv, uint32_t baudrate) uint32_t fractional_baud_value; uint64_t pclk_freq; - pclk_freq = MPFS_MSS_APB_AHB_CLK; + if (!priv->fpga) + { + pclk_freq = MPFS_MSS_APB_AHB_CLK; + } + else + { + pclk_freq = MPFS_FPGA_PERIPHERAL_CLK; + } /* Compute baud value based on requested baud rate and PCLK frequency. * The baud value is computed using the following equation: @@ -1027,6 +1355,13 @@ static void up_send(struct uart_dev_s *dev, int ch) { struct up_dev_s *priv = (struct up_dev_s *)dev->priv; +#ifdef HAVE_SERIAL_CONSOLE + if (dev == &CONSOLE_DEV && !dev->isconsole) + { + return; + } +#endif + while ((up_serialin(priv, MPFS_UART_LSR_OFFSET) & UART_LSR_THRE) == 0); @@ -1140,6 +1475,18 @@ void riscv_earlyserialinit(void) up_disableuartint(g_uart4port.priv, NULL); #endif +#ifdef CONFIG_MPFS_UART5 + up_disableuartint(g_uart5port.priv, NULL); +#endif + +#ifdef CONFIG_MPFS_UART6 + up_disableuartint(g_uart6port.priv, NULL); +#endif + +#ifdef CONFIG_MPFS_UART7 + up_disableuartint(g_uart7port.priv, NULL); +#endif + /* Configuration whichever one is the console */ #ifdef HAVE_SERIAL_CONSOLE @@ -1183,6 +1530,15 @@ void riscv_serialinit(void) #ifdef CONFIG_MPFS_UART4 uart_register("/dev/ttyS4", &g_uart4port); #endif +#ifdef CONFIG_MPFS_UART5 + uart_register("/dev/ttyS5", &g_uart5port); +#endif +#ifdef CONFIG_MPFS_UART6 + uart_register("/dev/ttyS6", &g_uart6port); +#endif +#ifdef CONFIG_MPFS_UART7 + uart_register("/dev/ttyS7", &g_uart7port); +#endif } /**************************************************************************** @@ -1198,6 +1554,12 @@ int up_putc(int ch) #ifdef HAVE_SERIAL_CONSOLE struct up_dev_s *priv = (struct up_dev_s *)CONSOLE_DEV.priv; uint32_t ier; + + if (!CONSOLE_DEV.isconsole) + { + return ch; + } + up_disableuartint(priv, &ier); #endif diff --git a/arch/risc-v/src/mpfs/mpfs_tamper.c b/arch/risc-v/src/mpfs/mpfs_tamper.c new file mode 100644 index 0000000000000..4729854ac0283 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_tamper.c @@ -0,0 +1,396 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_tamper.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register base-addresses */ + +#define MPFS_TAMPER_CTRL_BASE 0x4b00c000 +#define MPFS_TAMPER_TVS_BASE 0x4b00d000 + +/* CTRL Register offsets */ + +#define MPFS_SELECTED_EVENTS_OFFSET 0x00 +#define MPFS_STATUS_EVENTS_OFFSET 0x04 +#define MPFS_CLEAR_EVENTS_OFFSET 0x08 +#define MPFS_ENABLE_EVENTS_OFFSET 0x0c +#define MPFS_ENABLE_TVS_OFFSET 0x10 +#define MPFS_RESET_REASON_OFFSET 0x14 +#define MPFS_TAMPER_RESPONSE_OFFSET 0x18 + +/* Selected eventlist */ + +#define MPFS_SELECTED_EVENTS (MPFS_TAMPER_CTRL_BASE + \ + MPFS_SELECTED_EVENTS_OFFSET) + +#define FLAG_JTAG_ACTIVE (1 << 0) +#define FLAG_MESH_ERROR (1 << 1) +#define FLAG_CLOCK_MONITOR_GLITCH (1 << 2) +#define FLAG_CLOCK_MONITOR_FREQ (1 << 3) +#define FLAG_SECDED (1 << 4) +#define FLAG_SCB_BUS_ERROR (1 << 5) +#define FLAG_SC_WATCHDOG (1 << 6) +#define FLAG_LOCK_ERROR (1 << 7) +#define FLAG_DIGEST (1 << 8) +#define FLAG_INST_PASSCODE_FAIL (1 << 9) +#define FLAG_INST_KEY_VALIDATION_FAIL (1 << 10) +#define FLAG_INST_UNUSED (1 << 11) +#define FLAG_BITSTREAM_AUTHENTICATION_FAIL (1 << 12) +#define FLAG_DETECT_LOW_1P0 (1 << 13) +#define FLAG_DETECT_LOW_1P8 (1 << 14) +#define FLAG_DETECT_LOW_2P5 (1 << 15) +#define FLAG_DETECT_HIGH_1P0 (1 << 16) +#define FLAG_DETECT_HIGH_1P8 (1 << 17) +#define FLAG_DETECT_HIGH_2P5 (1 << 18) +#define FLAG_DETECT_TEMPERATURE_LOW (1 << 19) +#define FLAG_DETECT_TEMPERATURE_HIGH (1 << 20) + +#define FLAGS_ALL 0x1fffff +#define FLAG_BITS 21 + +/* Status eventlist */ + +#define MPFS_STATUS_EVENTS (MPFS_TAMPER_CTRL_BASE + \ + MPFS_STATUS_EVENTS_OFFSET) + +/* Clear eventlist */ + +#define MPFS_CLEAR_EVENTS (MPFS_TAMPER_CTRL_BASE + \ + MPFS_CLEAR_EVENTS_OFFSET) + +/* Enable eventlist */ + +#define MPFS_ENABLE_EVENTS (MPFS_TAMPER_CTRL_BASE + \ + MPFS_ENABLE_EVENTS_OFFSET) + +/* Enable TVS */ + +#define MPFS_ENABLE_TVS (MPFS_TAMPER_CTRL_BASE +\ + MPFS_ENABLE_TVS_OFFSET) + +#define MPFS_ENABLE_TVS_MONITORING (1 << 0) +#define MPFS_ENABLE_VOLTAGE_MONITORING (1 << 1) + +/* Reset reason */ + +#define MPFS_RESET_REASON (MPFS_TAMPER_CTRL_BASE + \ + MPFS_RESET_REASON_OFFSET) + +/* Clock and reset */ + +#define MPFS_SYSREG_SOFT_RESET_CR (MPFS_SYSREG_BASE + \ + MPFS_SYSREG_SOFT_RESET_CR_OFFSET) +#define MPFS_SYSREG_SUBBLK_CLOCK_CR (MPFS_SYSREG_BASE + \ + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET) + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +/* Mesh system defines */ + +#define MPFS_MESH_CR 0x200020b0 +#define MPFS_MESH_START (1 << 0) + +/* Debug output defines, info promoted to _err for visibility */ + +#ifdef CONFIG_DEBUG_ERROR +# define tinfo _err +#else +# define tinfo _none +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_tamper_event_string + * + * Description: + * Tamper event to string function + * + * Input Parameters: + * List of events + * + * Returned Value: + * Readable string + * + ****************************************************************************/ + +static const char *mpfs_tamper_event_string(uint32_t eventlist) +{ + int i; + + static const char *const names[] = + { + "JTAG ACTIVE", + "MESH ERROR", + "CLOCK MONITOR GLITCH", + "CLOCK MONITOR FREQ", + "SECDED", + "SCB BUS ERROR", + "SC WATCHDOG", + "LOCK ERROR", + "DIGEST", + "PASSCODE FAIL", + "KEY VALIDATION FAIL", + "INST UNUSED", + "BITSTREAM AUTH FAIL", + "LOW 1P0", + "LOW 1P8", + "LOW 2P5", + "HIGH 1P0", + "HIGH 1P8", + "HIGH 2P5", + "TEMPERATURE LOW", + "TEMPERATURE HIGH", + }; + + for (i = 0; i < ARRAY_SIZE(names); i++) + { + if ((1 << i) & eventlist) + { + break; + } + } + + if (i >= ARRAY_SIZE(names)) + { + return "UNDEFINED"; + } + + return names[i]; +} + +/**************************************************************************** + * Name: mpfs_tamper_interrupt + * + * Description: + * Tamper intinfoupt handler + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int mpfs_tamper_interrupt(int irq, void *context, void *arg) +{ + uint32_t eventlist; + uint32_t sel; + uint32_t status; + uint32_t clr; + uint32_t enabled; + uint32_t entvs; + int i; + + sel = getreg32(MPFS_SELECTED_EVENTS); + status = getreg32(MPFS_STATUS_EVENTS); + clr = getreg32(MPFS_CLEAR_EVENTS); + enabled = getreg32(MPFS_ENABLE_EVENTS); + entvs = getreg32(MPFS_ENABLE_TVS); + + eventlist = sel; + + if (eventlist) + { + tinfo("**********************************************************\n"); + tinfo("Tamper detection has caught out the following event(s):\n"); + for (i = 0; i < FLAG_BITS; i++) + { + if ((1 << i) & eventlist) + { + tinfo(" <%s>\n", mpfs_tamper_event_string(eventlist)); + eventlist &= ~(1 << i); + } + } + + tinfo("Regs: 0x00: 0x%x, 0x04: 0x%x, 0x08: 0x%x, 0x0c: 0x%x," + " 0x10: 0x%x\n", + sel, status, clr, enabled, entvs); + tinfo("**********************************************************\n"); + } + + putreg32(sel, MPFS_CLEAR_EVENTS); + + return 0; +} + +/**************************************************************************** + * Name: mpfs_tamper_tests + * + * Description: + * Various tamper tests for testing + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef TAMPER_TESTS +extern int mpfs_systemservice_init(); +extern int mpfs_sys_get_serial_number(uint8_t *out_sn, uint16_t mb_offset); +extern int mpfs_sys_query_security(uint8_t *out_security_resp, + uint16_t mb_offset); +extern int mpfs_sys_query_design_information(uint8_t *out_security_resp, + uint16_t mb_offset); +extern int mpfs_sys_query_device_certificate(uint8_t *out_security_resp, + uint16_t mb_offset); +extern uint16_t mpfs_sys_unlock_debug_passcode(uint8_t *cmd_data, + uint16_t mb_offset, + uint16_t resp_offset); +extern void test_ecdsa(void); + +static void mpfs_tamper_tests(void) +{ + uint8_t buf[1024 + 4]; + + mpfs_systemservice_init(); + + /* Some of the functions do not exist */ + + mpfs_sys_get_serial_number(buf, 0); + mpfs_sys_query_security(buf, 0); + mpfs_sys_query_design_information(buf, 0); + mpfs_sys_query_device_certificate(buf, 0); + mpfs_sys_unlock_debug_passcode(buf, 0, 0); + test_ecdsa(); + mpfs_sys_authenticate_iap_image(0); +} +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_tamper_enable + * + * Description: + * Enables the tamper service + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void mpfs_tamper_enable(void) +{ + int ret; + + modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, + SYSREG_SOFT_RESET_CR_FPGA | SYSREG_SOFT_RESET_CR_FIC3, + 0); + + modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0, + SYSREG_SUBBLK_CLOCK_CR_FIC3); + + tinfo("Enabling Tamper detection - if no FPGA support, will hang here\n"); + tinfo("Tamper reset reason 0x%x\n", getreg32(MPFS_RESET_REASON)); + + /* Enable events */ + + putreg32(FLAGS_ALL, MPFS_ENABLE_EVENTS); + putreg32(MPFS_ENABLE_TVS_MONITORING | MPFS_ENABLE_VOLTAGE_MONITORING, + MPFS_ENABLE_TVS); + + /* Start the mesh system */ + + modifyreg32(MPFS_MESH_CR, 0, MPFS_MESH_START); + + ret = irq_attach(MPFS_IRQ_FABRIC_F2H_10, mpfs_tamper_interrupt, NULL); + + if (ret == 0) + { + up_enable_irq(MPFS_IRQ_FABRIC_F2H_10); + } + else + { + tinfo("Tamper IRQ attach failed"); + } + +#ifdef TAMPER_TESTS + mpfs_tamper_tests(); +#endif +} + +/**************************************************************************** + * Name: mpfs_tamper_disable + * + * Description: + * Disables tamper service + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void mpfs_tamper_disable(void) +{ + modifyreg32(MPFS_MESH_CR, MPFS_MESH_START, 0); + + up_disable_irq(MPFS_IRQ_FABRIC_F2H_10); + irq_detach(MPFS_IRQ_FABRIC_F2H_10); + + putreg32(0x00, MPFS_ENABLE_EVENTS); + putreg32(0, MPFS_ENABLE_TVS); +} diff --git a/arch/risc-v/src/mpfs/mpfs_tamper.h b/arch/risc-v/src/mpfs/mpfs_tamper.h new file mode 100644 index 0000000000000..800c4471d956a --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_tamper.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_tamper.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_TAMPER_H +#define __ARCH_RISCV_SRC_MPFS_MPFS_TAMPER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mpfs_tamper_enable + * + * Description: + * Enables the tamper service + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void mpfs_tamper_enable(void); + +/**************************************************************************** + * Name: mpfs_tamper_disable + * + * Description: + * Disables tamper service + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void mpfs_tamper_disable(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_TAMPER_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_timerisr.c b/arch/risc-v/src/mpfs/mpfs_timerisr.c index 3a43fa278f18e..b8c635811fef9 100644 --- a/arch/risc-v/src/mpfs/mpfs_timerisr.c +++ b/arch/risc-v/src/mpfs/mpfs_timerisr.c @@ -24,7 +24,6 @@ #include -#include #include #include #include @@ -32,11 +31,8 @@ #include #include #include -#include -#include "hardware/mpfs_clint.h" #include "riscv_internal.h" -#include "riscv_mtimer.h" #include "mpfs.h" #include "mpfs_clockconfig.h" @@ -45,7 +41,81 @@ * Pre-processor Definitions ****************************************************************************/ -#define MTIMER_FREQ MPFS_MSS_RTC_TOGGLE_CLK +#define TICK_COUNT (MPFS_MSS_RTC_TOGGLE_CLK / TICK_PER_SEC) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifndef CONFIG_BUILD_KERNEL +static bool _b_tick_started; +static uint64_t *_mtime_cmp; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static uint64_t get_current(void) +{ +#ifndef CONFIG_BUILD_KERNEL + if (!_b_tick_started) + { + _b_tick_started = true; + return getreg64(MPFS_CLINT_MTIME); + } + else + { + return getreg64(_mtime_cmp); + } +#else + return riscv_sbi_get_time(); +#endif +} + +static void set_next(uint64_t next) +{ +#ifndef CONFIG_BUILD_KERNEL + putreg64(next, _mtime_cmp); +#else + riscv_sbi_set_timer(next); +#endif +} + +/**************************************************************************** + * Name: mpfs_reload_mtimecmp + ****************************************************************************/ + +static void mpfs_reload_mtimecmp(void) +{ + irqstate_t flags = spin_lock_irqsave(NULL); + + uint64_t current; + uint64_t next; + + current = get_current(); + uint64_t tick = TICK_COUNT; + next = current + tick; + + set_next(next); + + spin_unlock_irqrestore(NULL, flags); +} + +/**************************************************************************** + * Name: mpfs_timerisr + ****************************************************************************/ + +static int mpfs_timerisr(int irq, void *context, void *arg) +{ + mpfs_reload_mtimecmp(); + + /* Process timer interrupt */ + + nxsched_process_timer(); + + return 0; +} /**************************************************************************** * Public Functions @@ -62,15 +132,22 @@ void up_timer_initialize(void) { +#ifndef CONFIG_BUILD_KERNEL /* what is our timecmp address for this hart */ uintptr_t hart_id = riscv_mhartid(); + _mtime_cmp = (uint64_t *)MPFS_CLINT_MTIMECMP0 + hart_id; +#endif + + /* Attach timer interrupt handler */ + + irq_attach(RISCV_IRQ_TIMER, mpfs_timerisr, NULL); + + /* Reload CLINT mtimecmp */ - struct oneshot_lowerhalf_s *lower = riscv_mtimer_initialize( - MPFS_CLINT_MTIME, MPFS_CLINT_MTIMECMP0 + hart_id * sizeof(uintptr_t), - RISCV_IRQ_TIMER, MTIMER_FREQ); + mpfs_reload_mtimecmp(); - DEBUGASSERT(lower); + /* And enable the timer interrupt */ - up_alarm_set_lowerhalf(lower); + up_enable_irq(RISCV_IRQ_TIMER); } diff --git a/arch/risc-v/src/mpfs/mpfs_usb.c b/arch/risc-v/src/mpfs/mpfs_usb.c index fec9deb8fd823..3c6be8ade298f 100644 --- a/arch/risc-v/src/mpfs/mpfs_usb.c +++ b/arch/risc-v/src/mpfs/mpfs_usb.c @@ -124,10 +124,16 @@ # define MSB 1 #endif +#ifndef MPFS_USB_DMA_ADDR_UPPER_OFFSET +# define MPFS_USB_DMA_ADDR_UPPER_OFFSET 0x14u +#endif + #define MPFS_NUM_USB_PKT 1 #define MPFS_MIN_EP_FIFO_SIZE 8 #define MPFS_USB_REG_MAX 0x2000 +#define LINKDEAD_THRESHOLD 20 + /* Request queue operations *************************************************/ #define mpfs_rqempty(q) ((q)->head == NULL) @@ -224,6 +230,7 @@ static void mpfs_epset_reset(struct mpfs_usbdev_s *priv, uint16_t epset); static struct mpfs_usbdev_s g_usbd; static uint8_t g_clkrefs; +static bool g_linkdead; static const struct usbdev_epops_s g_epops = { @@ -767,11 +774,26 @@ static int mpfs_req_wrsetup(struct mpfs_usbdev_s *priv, if (nbytes > packetsize) { - ret = mpfs_write_tx_fifo(buf, packetsize, epno); - if (ret != OK) + if (privep->linkdead < LINKDEAD_THRESHOLD) { - privep->epstate = USB_EPSTATE_IDLE; - return ret; + ret = mpfs_write_tx_fifo(buf, packetsize, epno); + if (ret != OK) + { + privep->linkdead++; + privep->epstate = USB_EPSTATE_IDLE; + return ret; + } + else + { + privep->linkdead = 0; + } + } + else + { + /* We're in trouble, remote has likely closed */ + + g_linkdead = true; + return -EIO; } if (epno == EP0) @@ -792,11 +814,26 @@ static int mpfs_req_wrsetup(struct mpfs_usbdev_s *priv, } else { - ret = mpfs_write_tx_fifo(buf, nbytes, epno); - if (ret != OK) + if (privep->linkdead < LINKDEAD_THRESHOLD) { - privep->epstate = USB_EPSTATE_IDLE; - return ret; + ret = mpfs_write_tx_fifo(buf, nbytes, epno); + if (ret != OK) + { + privep->linkdead++; + privep->epstate = USB_EPSTATE_IDLE; + return ret; + } + else + { + privep->linkdead = 0; + } + } + else + { + /* We're in trouble, remote has likely closed */ + + g_linkdead = true; + return -EIO; } } @@ -2439,6 +2476,8 @@ static void mpfs_reset(struct mpfs_usbdev_s *priv) mpfs_req_cancel(privep, -ESHUTDOWN); + privep->linkdead = 0; + /* Reset endpoint status */ privep->stalled = false; @@ -3438,7 +3477,7 @@ static int mpfs_usb_interrupt(int irq, void *context, void *arg) if (pending_tx_ep != 0) { - for (i = 1; i < MPFS_USB_NENDPOINTS; i++) + for (i = 1; i < (MPFS_USB_NENDPOINTS / 2 + 1); i++) { if ((pending_tx_ep & (1 << i)) != 0) { @@ -3449,13 +3488,37 @@ static int mpfs_usb_interrupt(int irq, void *context, void *arg) if (pending_rx_ep != 0) { - for (i = 0; i < MPFS_USB_NENDPOINTS; i++) + for (i = 1; i < (MPFS_USB_NENDPOINTS / 2 + 1); i++) { + /* Check if dead connections are back in business */ + + if (g_linkdead) + { + /* This releases all tx counterparts with linkdead flag + * set, which is a problem if only some endpoints are + * closed on the remote; whereas some are functioning; + * for example ACM and mass storage; now the functioning + * one likely marks the closed ones as no longer dead. + * Please note that tx counterparts have MPFS_EPIN_START + * offset on top of the rx eps. + * + * For clarity, the eplist[] is as follows: + * eplist: 0: ep0, + * 1-4: ep1rx, ep2rx, ep3rx, ep4rx, + * 5-8: ep1tx, ep2tx, ep3tx, ep4tx + */ + + struct mpfs_ep_s *privep = &priv->eplist[i + MPFS_EPIN_START]; + privep->linkdead = 0; + } + if ((pending_rx_ep & (1 << i)) != 0) { mpfs_ep_rx_interrupt(priv, i); } } + + g_linkdead = false; } if ((isr & SUSPEND_IRQ_MASK) != 0) @@ -3613,7 +3676,7 @@ static void mpfs_usb_iomux(void) #ifdef CONFIG_USBDEV_DMA /* DMA operations need to open the USB PMP registers for proper - * operation. If not configured, apply default settings. + * operation. */ uint64_t pmpcfg_usb_x; @@ -3622,28 +3685,24 @@ static void mpfs_usb_iomux(void) if ((pmpcfg_usb_x & 0x1ffffff000000000llu) != 0x1f00000000000000llu) { uerr("Please check the MPFS_PMPCFG_USB_0 register.\n"); - putreg64(0x1f00000fffffffffllu, MPFS_PMPCFG_USB_0); } pmpcfg_usb_x = getreg64(MPFS_PMPCFG_USB_1); if ((pmpcfg_usb_x & 0x1ffffff000000000llu) != 0x1f00000000000000llu) { uerr("Please check the MPFS_PMPCFG_USB_1 register.\n"); - putreg64(0x1f00000fffffffffllu, MPFS_PMPCFG_USB_1); } pmpcfg_usb_x = getreg64(MPFS_PMPCFG_USB_2); if ((pmpcfg_usb_x & 0x1ffffff000000000llu) != 0x1f00000000000000llu) { uerr("Please check the MPFS_PMPCFG_USB_2 register.\n"); - putreg64(0x1f00000fffffffffllu, MPFS_PMPCFG_USB_2); } pmpcfg_usb_x = getreg64(MPFS_PMPCFG_USB_3); if ((pmpcfg_usb_x & 0x1ffffff000000000llu) != 0x1f00000000000000llu) { uerr("Please check the MPFS_PMPCFG_USB_3 register.\n"); - putreg64(0x1f00000fffffffffllu, MPFS_PMPCFG_USB_3); } #endif } @@ -3680,6 +3739,10 @@ static void mpfs_hw_setup(struct mpfs_usbdev_s *priv) modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, SYSREG_SOFT_RESET_CR_USB | SYSREG_SOFT_RESET_CR_FPGA, 0); + /* Set USB upper address offset to enable USB DMA support for himen */ + + mpfs_putreg32(MPFS_USB_DMA_ADDR_UPPER_OFFSET, MPFS_USB_DMA_ADDR_UPPER_REG); + /* Reset the controller */ mpfs_putreg8(SOFT_RESET_REG_MASK, MPFS_USB_SOFT_RST); diff --git a/arch/risc-v/src/mpfs/mpfs_userspace.c b/arch/risc-v/src/mpfs/mpfs_userspace.c index a4409e2dcb088..7c13fd6a41ac3 100644 --- a/arch/risc-v/src/mpfs/mpfs_userspace.c +++ b/arch/risc-v/src/mpfs/mpfs_userspace.c @@ -31,6 +31,7 @@ #include #include +#include "hardware/mpfs_clint.h" #include "mpfs_userspace.h" #include "riscv_internal.h" @@ -53,7 +54,7 @@ #define PGT_L1_SIZE (512) /* Enough to map 512 GiB */ #define PGT_L2_SIZE (512) /* Enough to map 1 GiB */ -#define PGT_L3_SIZE (1024) /* Enough to map 4 MiB */ +#define PGT_L3_SIZE (2048) /* Enough to map 8 MiB */ #define SLAB_COUNT (sizeof(m_l3_pgtable) / RV_MMU_PAGE_SIZE) @@ -248,6 +249,11 @@ static void configure_mmu(void) map_region(UFLASH_START, UFLASH_START, UFLASH_SIZE, MMU_UTEXT_FLAGS); map_region(USRAM_START, USRAM_START, USRAM_SIZE, MMU_UDATA_FLAGS); + /* Map the MTIME counter to the start of USR IO region */ + + map_region(MPFS_CLINT_MTIME & (~RV_MMU_PAGE_MASK), USRIO_START, + RV_MMU_PAGE_SIZE, PTE_R | PTE_U | PTE_G); + /* Connect the L1 and L2 page tables */ mmu_ln_setentry(1, PGT_L1_VBASE, PGT_L2_PBASE, UFLASH_START, PTE_G); diff --git a/arch/risc-v/src/opensbi/Make.defs b/arch/risc-v/src/opensbi/Make.defs index 4b0f37d1116be..c893e17a0a28f 100644 --- a/arch/risc-v/src/opensbi/Make.defs +++ b/arch/risc-v/src/opensbi/Make.defs @@ -44,9 +44,9 @@ SBI_DIR := opensbi OPENSBI_UNPACK = opensbi-3rdparty OPENSBI_COMMIT = fbaaafe808f3da7745760d757c436ef1b293d3ed -OPENSBI_URL = https://github.com/riscv-software-src/opensbi/tarball +OPENSBI_URL = https://github.com/tiiuae/opensbi/tarball OPENSBI_TARBALL = opensbi.tar.gz -OPENSBI_DIR = riscv-software-src-opensbi-fbaaafe +OPENSBI_DIR = tiiuae-opensbi-fbaaafe $(OPENSBI_TARBALL): $(call DOWNLOAD,$(OPENSBI_URL),$(OPENSBI_COMMIT),opensbi/$(OPENSBI_TARBALL)) diff --git a/boards/Kconfig b/boards/Kconfig index 720b6120678f7..7be086a526961 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -2115,6 +2115,14 @@ config ARCH_BOARD_IMX8QM_MEK This options selects support for NuttX on the NXP i.MX8 QuadMax CPUs MEK configure board with ARM Cortex-A53. +config ARCH_BOARD_IMX93_EVK + bool "NXP i.MX93 CPUs EVK board" + depends on ARCH_CHIP_IMX93 + select ARCH_HAVE_IRQBUTTONS + ---help--- + This options selects support for NuttX on the NXP i.MX93 CPUs EVK + board with ARM Cortex-A55. + config ARCH_BOARD_SAMA5D2_XULT bool "Atmel SAMA5D2 Xplained Ultra development board" depends on ARCH_CHIP_ATSAMA5D27 @@ -3284,6 +3292,7 @@ config ARCH_BOARD default "fvp-armv8r" if ARCH_BOARD_FVP_ARMV8R default "fvp-armv8r-aarch32" if ARCH_BOARD_FVP_ARMV8R_AARCH32 default "imx8qm-mek" if ARCH_BOARD_IMX8QM_MEK + default "imx93-evk" if ARCH_BOARD_IMX93_EVK default "sama5d2-xult" if ARCH_BOARD_SAMA5D2_XULT default "giant-board" if ARCH_BOARD_GIANT_BOARD default "jupiter-nano" if ARCH_BOARD_JUPITER_NANO @@ -3497,6 +3506,9 @@ endif if ARCH_BOARD_IMX8QM_MEK source "boards/arm64/imx8/imx8qm-mek/Kconfig" endif +if ARCH_BOARD_IMX93_EVK +source "boards/arm64/imx9/imx93-evk/Kconfig" +endif if ARCH_BOARD_IMXRT1020_EVK source "boards/arm/imxrt/imxrt1020-evk/Kconfig" endif diff --git a/boards/arm64/a64/pinephone/scripts/dramboot.ld b/boards/arm64/a64/pinephone/scripts/dramboot.ld index 15c82c9d32304..f5f515d4b819a 100644 --- a/boards/arm64/a64/pinephone/scripts/dramboot.ld +++ b/boards/arm64/a64/pinephone/scripts/dramboot.ld @@ -33,6 +33,7 @@ SECTIONS _start = .; .text : { _stext = .; /* Text section */ + *(.start .start.*) /* Place __start here */ *(.text) *(.text.cold) *(.text.unlikely) diff --git a/boards/arm64/fvp-v8r/fvp-armv8r/scripts/dramboot.ld b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/dramboot.ld index ec2d6956c52ad..50d5ba78d41cd 100644 --- a/boards/arm64/fvp-v8r/fvp-armv8r/scripts/dramboot.ld +++ b/boards/arm64/fvp-v8r/fvp-armv8r/scripts/dramboot.ld @@ -33,6 +33,7 @@ SECTIONS _start = .; .text : { _stext = .; /* Text section */ + *(.start .start.*) /* Place __start here */ *(.text) *(.text.cold) *(.text.unlikely) diff --git a/boards/arm64/imx8/imx8qm-mek/scripts/dramboot.ld b/boards/arm64/imx8/imx8qm-mek/scripts/dramboot.ld index 160a5f8f86db7..24e385d9948b5 100644 --- a/boards/arm64/imx8/imx8qm-mek/scripts/dramboot.ld +++ b/boards/arm64/imx8/imx8qm-mek/scripts/dramboot.ld @@ -33,6 +33,7 @@ SECTIONS _start = .; .text : { _stext = .; /* Text section */ + *(.start .start.*) /* Place __start here */ *(.text) *(.text.cold) *(.text.unlikely) diff --git a/boards/arm64/imx9/imx93-evk/Kconfig b/boards/arm64/imx9/imx93-evk/Kconfig new file mode 100644 index 0000000000000..7a671a3a358df --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/Kconfig @@ -0,0 +1,7 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_IMX9QM_MEK +endif diff --git a/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig b/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig new file mode 100644 index 0000000000000..90729bcb457ed --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig @@ -0,0 +1,62 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_ARCH="arm64" +CONFIG_ARCH_ARM64=y +CONFIG_ARCH_BOARD="imx93-evk" +CONFIG_ARCH_BOARD_IMX93_EVK=y +CONFIG_ARCH_CHIP="imx9" +CONFIG_ARCH_CHIP_IMX93=y +CONFIG_ARCH_CHIP_IMX9=y +CONFIG_ARCH_EARLY_PRINT=y +CONFIG_ARCH_INTERRUPTSTACK=4096 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SCHED=y +CONFIG_DEBUG_SCHED_ERROR=y +CONFIG_DEBUG_SCHED_INFO=y +CONFIG_DEBUG_SCHED_WARN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_TASK_STACKSIZE=8192 +CONFIG_DEV_ZERO=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=8192 +CONFIG_IMX9_GPIO_IRQ=y +CONFIG_IMX9_UART1=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAMLOG=y +CONFIG_RAM_SIZE=134217728 +CONFIG_RAM_START=0x80000000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SPINLOCK=y +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=3 +CONFIG_START_YEAR=2022 +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_SYSTEM=y +CONFIG_SYSTEM_TIME64=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART1_SERIAL_CONSOLE=y diff --git a/boards/arm64/imx9/imx93-evk/include/board.h b/boards/arm64/imx9/imx93-evk/include/board.h new file mode 100644 index 0000000000000..e8fd207609ecc --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/include/board.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * boards/arm64/imx9/imx93-evk/include/board.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM64_IMX9_IMX93_EVK_INCLUDE_BOARD_H +#define __BOARDS_ARM64_IMX9_IMX93_EVK_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM64_IMX9_IMX93_EVK_INCLUDE_BOARD_H */ diff --git a/boards/arm64/imx9/imx93-evk/include/board_memorymap.h b/boards/arm64/imx9/imx93-evk/include/board_memorymap.h new file mode 100644 index 0000000000000..07649afbc5df5 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/include/board_memorymap.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * boards/arm64/imx9/imx93-evk/include/board_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM64_IMX9_IMX93_EVK_INCLUDE_BOARD_MEMORYMAP_H +#define __BOARDS_ARM64_IMX9_IMX93_EVK_INCLUDE_BOARD_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM64_IMX9_IMX93_EVK_INCLUDE_BOARD_MEMORYMAP_H */ diff --git a/boards/arm64/imx9/imx93-evk/scripts/Make.defs b/boards/arm64/imx9/imx93-evk/scripts/Make.defs new file mode 100644 index 0000000000000..dd8d6fac4b286 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/scripts/Make.defs @@ -0,0 +1,48 @@ +############################################################################ +# boards/arm64/imx9/imx93-evk/scripts/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/arm64/src/Toolchain.defs + +LDSCRIPT = dramboot.ld + +ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +# NXFLAT module definitions + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)$(DELIM)binfmt$(DELIM)libnxflat$(DELIM)gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +# ELF module definitions + +CELFFLAGS = $(CFLAGS) -mlong-calls # --target1-abs +CXXELFFLAGS = $(CXXFLAGS) -mlong-calls # --target1-abs + +LDELFFLAGS = -r -e main +LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) diff --git a/boards/arm64/imx9/imx93-evk/scripts/dramboot.ld b/boards/arm64/imx9/imx93-evk/scripts/dramboot.ld new file mode 100644 index 0000000000000..f437d8d13745a --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/scripts/dramboot.ld @@ -0,0 +1,157 @@ +/**************************************************************************** + * boards/arm64/imx9/imx93-evk/scripts/dramboot.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +OUTPUT_ARCH(aarch64) + +ENTRY(__start) +EXTERN(__start) + +/* Memory is organized as follows: + * - Uboot reserved area is 0x00000000 - 0x00a00000 + * - NuttX is loaded to 0x80000000, u-boot expects us here + * - NuttX ROM and RAM are one continuous region, starting from 0x80000000 + with a size of 128MB + * - Heap memory is allocated from dram end to idlestack top + */ + +MEMORY +{ + dram (rwx) : ORIGIN = 0x80000000, LENGTH = 128M +} + +PHDRS +{ + /* R = 100, W = 010, X = 001 */ + + text PT_LOAD FLAGS(5); /* RX */ + rodata PT_LOAD FLAGS(4); /* R */ + data PT_LOAD FLAGS(6); /* RW */ +} + +SECTIONS +{ + .text : + { + _stext = ABSOLUTE(.); /* Text section */ + *(.start .start.*) /* Place __start here */ + *(.text .text.*) + *(.text.cold) + *(.text.unlikely) + *(.fixup) + *(.gnu.warning) + } > dram :text + + .init_section : + { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array .ctors)) + _einit = ABSOLUTE(.); + } > dram :text + + /* Vector table must be page aligned */ + + .vector : ALIGN(4096) + { + _vector_start = ABSOLUTE(.); + KEEP(*(.exc_vector_table)) + KEEP(*(".exc_vector_table.*")) + KEEP(*(.vectors)) + _vector_end = ABSOLUTE(.); + } > dram :text + + /* End of text data must be aligned to page boundary */ + + . = ALIGN(4096); + _etext = .; + _sztext = _etext - _stext; + + /* Start of RO data must be page aligned (mapped as read only) */ + + .rodata : ALIGN(4096) + { + _srodata = ABSOLUTE(.); /* Read-only data */ + *(.rodata .rodata.*) + *(.data.rel.ro) + *(.data.rel.ro.*) + } > dram :rodata + + /* End of RO data must be page aligned */ + + . = ALIGN(4096); + + _erodata = .; /* End of read-only data */ + _szrodata = _erodata - _srodata; + _eronly = .; /* End of read-only data */ + + .data : ALIGN(4096) + { + _sdata = ABSOLUTE(.); + *(.data.page_aligned) + *(.data .data.*) + . = ALIGN(8); + *(.data.rel) + *(.data.rel.*) + CONSTRUCTORS + . = ALIGN(8); + _edata = ABSOLUTE(.); + } > dram :data + + .bss : + { + . = ALIGN(8); + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + . = ALIGN(8); + _ebss = ABSOLUTE(.); + } > dram :data + + _szbss = _ebss - _sbss; + + .initstack : + { + _s_initstack = ABSOLUTE(.); + *(.initstack) + } > dram :data + + /* End of data must be page aligned */ + . = ALIGN(4096); + + g_idle_topstack = .; + _e_initstack = .; + _szdata = _e_initstack - _sdata; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.exit.text) + *(.exit.data) + *(.exitcall.exit) + *(.eh_frame) + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff --git a/boards/arm64/imx9/imx93-evk/scripts/imx93_ca55.JLinkScript b/boards/arm64/imx9/imx93-evk/scripts/imx93_ca55.JLinkScript new file mode 100644 index 0000000000000..483fc7005f202 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/scripts/imx93_ca55.JLinkScript @@ -0,0 +1,58 @@ +/* Adds custom i.MX93 logic to replace default procedures from JLink */ + +int ResetTarget(void) { + + JLINK_SYS_Report("-- Resetting target device..."); + + JLINK_TIF_ActivateTargetReset(); + JLINK_Delay_us(50000); // _Delay_us: Keep reset active for some time so possible glitch filters on target do not filter out reset pulse + JLINK_TIF_ReleaseTargetReset(); + + // + // This device requires a special reset as default reset does not work for this device. + // + JLINK_TARGET_Halt(); // Make sure that the CPU is halted when reset is called + + return 0; +} + +void ConfigTargetSettings(void) { + // JLINK_SYS_Report("J-Link script: Manually configuring JTAG chain"); + + // AP[0]: AHB-AP (IDR: 0x74770001) + // AP[1]: APB-AP (IDR: 0x44770002) + + JLINK_ExecCommand("CORESIGHT_AddAP Index=0 Type=AHB-AP"); // Connects to System Bus + JLINK_ExecCommand("CORESIGHT_AddAP Index=1 Type=APB-AP"); // Connects to CoreSight/A-core Platform (see APBIC) + JLINK_ExecCommand("CORESIGHT_AddAP Index=3 Type=DAP-AP"); // Connects to a Cortex-M33 + JLINK_ExecCommand("CORESIGHT_AddAP Index=4 Type=DAP-AP"); // Connects to a EdgeLock (Risc-V) + JLINK_ExecCommand("CORESIGHT_AddAP Index=6 Type=MDM-AP"); // Connects to a MDM + + // A55_0 + JLINK_ExecCommand("CORESIGHT_SetCoreBaseAddr = 0x40810000"); // Location in AP address space where debug registers of core are located + JLINK_ExecCommand("CORESIGHT_SetCSCTICoreBaseAddr = 0x40820000"); // Location in AP address space where CTI that connects to the core is located + + // A55_1 + //JLINK_ExecCommand("CORESIGHT_SetCoreBaseAddr = 0x40910000"); // Location in AP address space where debug registers of core are located + //JLINK_ExecCommand("CORESIGHT_SetCSCTICoreBaseAddr = 0x40920000"); // Location in AP address space where CTI that connects to the core is located + + // There is also a debug core at SetCoreBaseAddr = 0x40840000, but don't know what it is + + JTAG_AllowTAPReset = 1; // J-Link is allowed to use a TAP reset for JTAG-chain auto-detection + + JLINK_JTAG_IRPre = 0; // Sum of IRLen of all JTAG TAPs preceding the one we want to communicate with + JLINK_JTAG_DRPre = 0; // Number of JTAG TAPs preceding the one we want to communicate with + JLINK_JTAG_IRPost = 0; // Sum of IRLen of all JTAG TAPs following the one we want to communicate with + JLINK_JTAG_DRPost = 0; // Number of JTAG TAPs following the one we want to communicate with + JLINK_JTAG_IRLen = 4; // IRLen of device we want to communicate with + + JLINK_JTAG_SetDeviceId(0, 0x6BA00477); + + // For Cortex-A55: + JLINK_ExecCommand("CORESIGHT_SetIndexAPBAPToUse = 1"); + // For Cortex-M33: + // JLINK_ExecCommand("CORESIGHT_SetIndexAPBAPToUse = 3"); + + return 0; +} + diff --git a/boards/arm64/imx9/imx93-evk/src/Makefile b/boards/arm64/imx9/imx93-evk/src/Makefile new file mode 100644 index 0000000000000..d034d21b4b4b7 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/src/Makefile @@ -0,0 +1,29 @@ +############################################################################ +# boards/arm64/imx9/emx93-evk/src/Makefile +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(TOPDIR)/Make.defs + +CSRCS = imx9_boardinit.c imx9_bringup.c + +ifeq ($(CONFIG_BOARDCTL),y) +CSRCS += imx9_appinit.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm64/imx9/imx93-evk/src/imx93-evk.h b/boards/arm64/imx9/imx93-evk/src/imx93-evk.h new file mode 100644 index 0000000000000..5956c51fce815 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/src/imx93-evk.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * boards/arm64/imx9/imx93-evk/src/imx93-evk.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM64_IMX9_IMX93_EVK_SRC_IMX93_EVK_H +#define __BOARDS_ARM64_IMX9_IMX93_EVK_SRC_IMX93_EVK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Functions Definitions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_bringup + * + * Description: + * Bring up board features + * + ****************************************************************************/ + +#if defined(CONFIG_BOARDCTL) || defined(CONFIG_BOARD_LATE_INITIALIZE) +int imx9_bringup(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_ARM64_IMX9_IMX93_EVK_SRC_IMX93_EVK_H */ diff --git a/boards/arm64/imx9/imx93-evk/src/imx9_appinit.c b/boards/arm64/imx9/imx93-evk/src/imx9_appinit.c new file mode 100644 index 0000000000000..289395145ce57 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/src/imx9_appinit.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * boards/arm64/imx9/imx93-evk/src/imx9_appinit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "imx93-evk.h" + +#ifdef CONFIG_BOARDCTL + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value could be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ + UNUSED(arg); +#ifndef CONFIG_BOARD_LATE_INITIALIZE + /* Perform board initialization */ + + return imx9_bringup(); +#else + return OK; +#endif +} + +#endif /* CONFIG_BOARDCTL */ diff --git a/boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c b/boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c new file mode 100644 index 0000000000000..7443f92ccd263 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include "imx93-evk.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx9_memory_initialize + * + * Description: + * All i.MX8 architectures must provide the following entry point. This + * entry point is called early in the initialization before memory has + * been configured. This board-specific function is responsible for + * configuring any on-board memories. + * + * Logic in imx9_memory_initialize must be careful to avoid using any + * global variables because those will be uninitialized at the time this + * function is called. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void imx9_memory_initialize(void) +{ + /* SDRAM was initialized by a bootloader in the supported configurations. */ +} + +/**************************************************************************** + * Name: imx9_board_initialize + * + * Description: + * All i.MX8 architectures must provide the following entry point. This + * entry point is called in the initialization phase -- after + * imx_memory_initialize and after all memory has been configured and + * mapped but before any devices have been initialized. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void imx9_board_initialize(void) +{ +#ifdef CONFIG_ARCH_LEDS + /* Configure on-board LEDs if LED support has been selected. */ + +#endif +} + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional + * initialization call will be performed in the boot-up sequence to a + * function called board_late_initialize(). board_late_initialize() will be + * called immediately after up_intitialize() is called and just before the + * initial application is started. This additional initialization phase + * may be used, for example, to initialize board-specific device drivers. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ + /* Perform board initialization */ + + imx9_bringup(); +} +#endif /* CONFIG_BOARD_LATE_INITIALIZE */ diff --git a/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c b/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c new file mode 100644 index 0000000000000..a267b844503e3 --- /dev/null +++ b/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * boards/arm64/imx9/imx93-evk/src/imx9_bringup.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "imx93-evk.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: imx_bringup + * + * Description: + * Bring up board features + * + ****************************************************************************/ + +int imx9_bringup(void) +{ + int ret; + +#ifdef CONFIG_FS_PROCFS + /* Mount the procfs file system */ + + ret = nx_mount(NULL, "/proc", "procfs", 0, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount procfs at /proc: %d\n", ret); + } +#endif + + UNUSED(ret); + return OK; +} diff --git a/boards/arm64/qemu/qemu-armv8a/scripts/dramboot.ld b/boards/arm64/qemu/qemu-armv8a/scripts/dramboot.ld index c8857860ea1cd..c4cbc49957987 100644 --- a/boards/arm64/qemu/qemu-armv8a/scripts/dramboot.ld +++ b/boards/arm64/qemu/qemu-armv8a/scripts/dramboot.ld @@ -33,6 +33,7 @@ SECTIONS _start = .; .text : { _stext = .; /* Text section */ + *(.start .start.*) /* Place __start here */ *(.text) *(.text.cold) *(.text.unlikely) diff --git a/boards/arm64/rk3399/nanopi_m4/scripts/dramboot.ld b/boards/arm64/rk3399/nanopi_m4/scripts/dramboot.ld index bebe73fff0013..d202807ea601c 100644 --- a/boards/arm64/rk3399/nanopi_m4/scripts/dramboot.ld +++ b/boards/arm64/rk3399/nanopi_m4/scripts/dramboot.ld @@ -43,6 +43,7 @@ SECTIONS _start = .; .text : { _stext = .; /* Text section */ + *(.start .start.*) /* Place __start here */ *(.text) *(.text.cold) *(.text.unlikely) diff --git a/boards/arm64/rk3399/pinephonepro/scripts/dramboot.ld b/boards/arm64/rk3399/pinephonepro/scripts/dramboot.ld index e50ea0b0ea1c3..f3a47b2719846 100644 --- a/boards/arm64/rk3399/pinephonepro/scripts/dramboot.ld +++ b/boards/arm64/rk3399/pinephonepro/scripts/dramboot.ld @@ -34,6 +34,7 @@ SECTIONS _start = .; .text : { _stext = .; /* Text section */ + *(.start .start.*) /* Place __start here */ *(.text) *(.text.cold) *(.text.unlikely) diff --git a/boards/risc-v/mpfs/common/src/mpfs_emmcsd.c b/boards/risc-v/mpfs/common/src/mpfs_emmcsd.c index 25a0ed09d6638..217b66920d5b6 100644 --- a/boards/risc-v/mpfs/common/src/mpfs_emmcsd.c +++ b/boards/risc-v/mpfs/common/src/mpfs_emmcsd.c @@ -28,7 +28,7 @@ #include #include -#include "mpfs_emmcsd.h" +#include "mpfs_sdio.h" #include "board_config.h" /**************************************************************************** diff --git a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig new file mode 100644 index 0000000000000..b4c5cf0acff04 --- /dev/null +++ b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig @@ -0,0 +1,83 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_OS_API is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_NET_IPv4 is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +CONFIG_ALLOW_BSD_COMPONENTS=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="icicle" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ICICLE_MPFS=y +CONFIG_ARCH_CHIP="mpfs" +CONFIG_ARCH_CHIP_MPFS250T_FCVG484=y +CONFIG_ARCH_CHIP_MPFS=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=54000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_NET=y +CONFIG_DEBUG_NET_ERROR=y +CONFIG_DEBUG_NET_INFO=y +CONFIG_DEBUG_NET_WARN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_ZERO=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_HOSTNAME="icicle" +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MPFS_CANFD0=y +CONFIG_MPFS_CANFD1=y +CONFIG_MPFS_ENABLE_DPFPU=y +CONFIG_MPFS_HAVE_CANFD=y +CONFIG_MPFS_UART1=y +CONFIG_NET=y +CONFIG_NETDEV_IFINDEX=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NET_CAN=y +CONFIG_NET_CAN_SOCK_OPTS=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_UMOUNT=y +CONFIG_NSH_LINELEN=160 +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=1048576 +CONFIG_RAM_START=0x80200000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SERIAL_NPOLLWAITERS=2 +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=4 +CONFIG_START_YEAR=2021 +CONFIG_SYSLOG_COLOR_OUTPUT=y +CONFIG_SYSTEM_CLE_CMD_HISTORY=y +CONFIG_SYSTEM_COLOR_CLE=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_TIME64=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART1_SERIAL_CONSOLE=y diff --git a/boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig b/boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig index b7ee1caff5550..3d3911d46f140 100644 --- a/boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig @@ -47,7 +47,6 @@ CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y CONFIG_MM_IOB=y CONFIG_MPFS_IHC_CLIENT=y -CONFIG_MPFS_IHC_LINUX_ON_HART4=0 CONFIG_MPFS_IHC_NUTTX_ON_HART1=1 CONFIG_MPFS_IHC_NUTTX_ON_HART2=0 CONFIG_MPFS_UART1=y diff --git a/boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig b/boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig index 961ad494f19d7..53b56e22b689a 100644 --- a/boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig @@ -48,6 +48,7 @@ CONFIG_MEMSET_OPTSPEED=y CONFIG_MM_IOB=y CONFIG_MPFS_IHC_CLIENT=y CONFIG_MPFS_IHC_LINUX_ON_HART3=0 +CONFIG_MPFS_IHC_LINUX_ON_HART4=1 CONFIG_MPFS_IHC_RPMSG_CH2=y CONFIG_MPFS_UART2=y CONFIG_NSH_ARCHINIT=y diff --git a/boards/risc-v/mpfs/icicle/configs/standalone/defconfig b/boards/risc-v/mpfs/icicle/configs/standalone/defconfig new file mode 100644 index 0000000000000..532550067b6ce --- /dev/null +++ b/boards/risc-v/mpfs/icicle/configs/standalone/defconfig @@ -0,0 +1,61 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="icicle" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ICICLE_MPFS=y +CONFIG_ARCH_CHIP="mpfs" +CONFIG_ARCH_CHIP_MPFS250T_FCVG484=y +CONFIG_ARCH_CHIP_MPFS=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=54000 +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_FS_ERROR=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_HOSTNAME="icicle" +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MPFS_BOOTLOADER=y +CONFIG_MPFS_BOOT_HART=1 +CONFIG_MPFS_DDR_INIT=y +CONFIG_MPFS_ENABLE_DPFPU=y +CONFIG_MPFS_UART0=y +CONFIG_MPFS_UART1=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_MKDIR=y +CONFIG_NSH_DISABLE_RM=y +CONFIG_NSH_DISABLE_RMDIR=y +CONFIG_NSH_DISABLE_UMOUNT=y +CONFIG_NSH_LINELEN=160 +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=1048576 +CONFIG_RAM_START=0x08000000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_SCHED_HPWORK=y +CONFIG_START_MONTH=4 +CONFIG_START_YEAR=2021 +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_TIME64=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_UART1_BAUD=2000000 +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/risc-v/mpfs/icicle/include/board.h b/boards/risc-v/mpfs/icicle/include/board.h index 85834a553bc5e..9ccabcd94bc03 100644 --- a/boards/risc-v/mpfs/icicle/include/board.h +++ b/boards/risc-v/mpfs/icicle/include/board.h @@ -43,6 +43,8 @@ # define MPFS_SD_CLOCK_4BIT MPFS_MMC_CLOCK_25MHZ #endif +#define MPFS_USB_DMA_ADDR_UPPER_OFFSET 0x14u + /* Clocking TODO: */ #define MPFS_MSS_EXT_SGMII_REF_CLK (125000000UL) diff --git a/boards/risc-v/mpfs/icicle/include/board_memorymap.h b/boards/risc-v/mpfs/icicle/include/board_memorymap.h index 47cac1185796c..353112aa86d6d 100644 --- a/boards/risc-v/mpfs/icicle/include/board_memorymap.h +++ b/boards/risc-v/mpfs/icicle/include/board_memorymap.h @@ -65,6 +65,11 @@ #define USRAM_START (uintptr_t)__usram_start #define USRAM_SIZE (uintptr_t)__usram_size +/* User IO */ + +#define USRIO_START (uintptr_t)__usrio_start +#define USRIO_SIZE (uintptr_t)__usrio_size + /**************************************************************************** * Public Data ****************************************************************************/ @@ -95,4 +100,9 @@ extern uint8_t __uflash_size[]; extern uint8_t __usram_start[]; extern uint8_t __usram_size[]; +/* User IO (R) */ + +extern uint8_t __usrio_start[]; +extern uint8_t __usrio_size[]; + #endif /* __BOARDS_RISC_V_MPFS_ICICLE_INCLUDE_BOARD_MEMORYMAP_H */ diff --git a/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld b/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld index 071d7fd8e9072..087e8ac490b96 100644 --- a/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld +++ b/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld @@ -30,6 +30,8 @@ __uflash_start = ORIGIN(uflash); __uflash_size = LENGTH(uflash); __usram_start = ORIGIN(usram); __usram_size = LENGTH(usram); +__usrio_start = ORIGIN(usrio); +__usrio_size = LENGTH(usrio); /* Provide the kernel boundaries as well */ diff --git a/boards/risc-v/mpfs/icicle/scripts/ld-kernel.script b/boards/risc-v/mpfs/icicle/scripts/ld-kernel.script index f5586f08f3aa6..2806601d90bbd 100644 --- a/boards/risc-v/mpfs/icicle/scripts/ld-kernel.script +++ b/boards/risc-v/mpfs/icicle/scripts/ld-kernel.script @@ -28,6 +28,7 @@ MEMORY kflash (rx) : ORIGIN = 0x80000000, LENGTH = 2048K /* w/ cache */ ksram (rwx) : ORIGIN = 0x80200000, LENGTH = 2048K /* w/ cache */ pgram (rwx) : ORIGIN = 0x80400000, LENGTH = 4096K /* w/ cache */ + usrio (r) : ORIGIN = 0x80800000, LENGTH = 32K /* w/ cache */ } OUTPUT_ARCH("riscv") @@ -45,6 +46,11 @@ __ksram_end = ORIGIN(ksram) + LENGTH(ksram); __pgheap_start = ORIGIN(pgram); __pgheap_size = LENGTH(pgram); +/* User I/O */ + +__usrio_start = ORIGIN(usrio); +__usrio_size = LENGTH(usrio); + ENTRY(_stext) EXTERN(__start) SECTIONS diff --git a/boards/risc-v/mpfs/icicle/scripts/memory.ld b/boards/risc-v/mpfs/icicle/scripts/memory.ld index 890ba735baf8c..f31a88d4eaacc 100644 --- a/boards/risc-v/mpfs/icicle/scripts/memory.ld +++ b/boards/risc-v/mpfs/icicle/scripts/memory.ld @@ -25,4 +25,6 @@ MEMORY ksram (rwx) : ORIGIN = 0x80080000, LENGTH = 256K /* w/ cache */ usram (rwx) : ORIGIN = 0x800C0000, LENGTH = 256K /* w/ cache */ + + usrio (r) : ORIGIN = 0x80100000, LENGTH = 32K } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index be6130891b885..61469781069c0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -549,6 +549,13 @@ choice config ETH0_PHY_NONE bool "No PHY support" +config ETH0_PHY_MULTI + bool "Multiple PHYs are supported" + ---help--- + The Board will provide a list of PHYs to probe for. + The first one found on the bpard will be used. + This setting is not supported by all Ethernet drivers. + config ETH0_PHY_AM79C874 bool "AMD Am79C874 PHY" diff --git a/drivers/net/rpmsgdrv.c b/drivers/net/rpmsgdrv.c index 3f55c31584b21..00b8303be0693 100644 --- a/drivers/net/rpmsgdrv.c +++ b/drivers/net/rpmsgdrv.c @@ -591,6 +591,13 @@ static int net_rpmsg_drv_ept_cb(FAR struct rpmsg_endpoint *ept, void *data, FAR struct net_rpmsg_header_s *header = data; uint32_t command = header->command; +#ifdef CONFIG_MPFS_IHC_CLIENT + if (command != NET_RPMSG_TRANSFER) + { + return -EINVAL; + } +#endif + if (command < sizeof(g_net_rpmsg_drv_handler) / sizeof(g_net_rpmsg_drv_handler[0])) { @@ -609,6 +616,13 @@ static int net_rpmsg_drv_send_recv(FAR struct net_driver_s *dev, FAR struct net_rpmsg_drv_cookie_s cookie; int ret; + /* TODO: Only TRANSFER command is implemeted on Linux side */ + + if (command != NET_RPMSG_TRANSFER) + { + return 0; + } + nxsem_init(&cookie.sem, 0, 0); cookie.header = header; diff --git a/fs/shm/CMakeLists.txt b/fs/shm/CMakeLists.txt index d76fb17e3bcdd..d6770ea4f13c1 100644 --- a/fs/shm/CMakeLists.txt +++ b/fs/shm/CMakeLists.txt @@ -20,6 +20,6 @@ # Include POSIX message queue support -if(CONFIG_FS_SHM) +if(CONFIG_FS_SHMFS) target_sources(fs PRIVATE shm_open.c shm_unlink.c shmfs.c shmfs_alloc.c) endif() diff --git a/fs/shm/Kconfig b/fs/shm/Kconfig index 7ec28209a0bdb..77bdbe5a320f4 100644 --- a/fs/shm/Kconfig +++ b/fs/shm/Kconfig @@ -19,4 +19,4 @@ config FS_SHMFS_VFS_PATH The path to where shared memory objects will exist in the VFS namespace. -endif # FS_SHM +endif # FS_SHMFS diff --git a/fs/shm/shmfs.c b/fs/shm/shmfs.c index fef22222efd11..b7095907e7cf7 100644 --- a/fs/shm/shmfs.c +++ b/fs/shm/shmfs.c @@ -238,8 +238,13 @@ static int shmfs_truncate(FAR struct file *filep, off_t length) filep->f_inode->i_private = shmfs_alloc_object(length); if (!filep->f_inode->i_private) { + filep->f_inode->i_size = 0; ret = -EFAULT; } + else + { + filep->f_inode->i_size = length; + } } else if (object->length != length) { diff --git a/fs/shm/shmfs_alloc.c b/fs/shm/shmfs_alloc.c index 979fd4c3f4648..65fb74ca3efd4 100644 --- a/fs/shm/shmfs_alloc.c +++ b/fs/shm/shmfs_alloc.c @@ -22,7 +22,11 @@ * Included Files ****************************************************************************/ +#include + #include + +#include #include #include @@ -87,6 +91,12 @@ FAR struct shmfs_object_s *shmfs_alloc_object(size_t length) { break; } + else + { + /* Clear the page memory (requirement for truncate) */ + + up_addrenv_page_wipe((uintptr_t)pages[i]); + } } } diff --git a/fs/vfs/fs_stat.c b/fs/vfs/fs_stat.c index e6acc398580b6..200e629dcf7c1 100644 --- a/fs/vfs/fs_stat.c +++ b/fs/vfs/fs_stat.c @@ -278,12 +278,13 @@ int inode_stat(FAR struct inode *inode, FAR struct stat *buf, int resolve) } else #endif -#if defined(CONFIG_FS_SHM) +#if defined(CONFIG_FS_SHMFS) /* Check for shared memory */ if (INODE_IS_SHM(inode)) { buf->st_mode = S_IFSHM; + buf->st_size = inode->i_size; } else #endif diff --git a/include/cxx/cstdlib b/include/cxx/cstdlib index 34483cdf9c06e..8517f164231bb 100644 --- a/include/cxx/cstdlib +++ b/include/cxx/cstdlib @@ -28,6 +28,28 @@ #include #include +#include + +//*************************************************************************** +// Pre-processor Definitions +//*************************************************************************** + +#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) +#undef malloc +#undef free +#undef realloc +#undef memalign +#undef zalloc +#undef calloc + +#define malloc kmm_malloc +#define free kmm_free +#define realloc kmm_realloc +#define memalign kmm_memalign +#define zalloc kmm_zalloc +#define calloc kmm_calloc +#endif + //*************************************************************************** // Namespace //*************************************************************************** diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 2aee23fc8c7cb..785b113b94fe7 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -1378,7 +1378,7 @@ uintptr_t up_addrenv_page_vaddr(uintptr_t page); * vaddr - The virtual address. * * Returned Value: - * True if it is; false if it's not + * True if it is; false if it's not. * ****************************************************************************/ @@ -1386,6 +1386,25 @@ uintptr_t up_addrenv_page_vaddr(uintptr_t page); bool up_addrenv_user_vaddr(uintptr_t vaddr); #endif +/**************************************************************************** + * Name: up_addrenv_page_wipe + * + * Description: + * Wipe a page of physical memory, first mapping it into kernel virtual + * memory. + * + * Input Parameters: + * page - The page physical address. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_ADDRENV +void up_addrenv_page_wipe(uintptr_t page); +#endif + /**************************************************************************** * Name: up_addrenv_kmap_init * diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index f17a04f5eb0d3..3d2ccec42baf4 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -412,7 +412,7 @@ struct inode uint16_t i_flags; /* Flags for inode */ union inode_ops_u u; /* Inode operations */ ino_t i_ino; /* Inode serial number */ -#ifdef CONFIG_PSEUDOFS_FILE +#if defined(CONFIG_PSEUDOFS_FILE) || defined(CONFIG_FS_SHMFS) size_t i_size; /* The size of per inode driver */ #endif #ifdef CONFIG_PSEUDOFS_ATTRIBUTES diff --git a/include/nuttx/net/mii.h b/include/nuttx/net/mii.h index 623610cc26bd1..cbc818a2d07e1 100644 --- a/include/nuttx/net/mii.h +++ b/include/nuttx/net/mii.h @@ -21,11 +21,14 @@ #ifndef __INCLUDE_NUTTX_NET_MII_H #define __INCLUDE_NUTTX_NET_MII_H +#ifndef __ASSEMBLY__ + /**************************************************************************** * Included Files ****************************************************************************/ #include +#include /**************************************************************************** * Pre-processor Definitions @@ -62,12 +65,14 @@ /* AR8031: */ +#define MII_AR8031_NAME "AR8031" #define MII_AR8031_PSSR 0x11 /* Phy-Specific Status Register */ /* National Semiconductor DP83840: 0x07-0x11, 0x14, 0x1a, 0x1d-0x1f * reserved */ +#define MII_DP83840_NAME "DP83840" #define MII_DP83840_COUNTER 0x12 /* Disconnect counter */ #define MII_DP83840_FCSCOUNTER 0x13 /* False carrier sense counter */ #define MII_DP83840_NWAYTEST 0x14 /* N-way auto-neg test reg */ @@ -80,6 +85,7 @@ /* Am79c874: 0x08-0x0f, 0x14, 0x16, 0x19-0x1f reserved */ +#define MII_AM79C874_NAME "AM79C874" #define MII_AM79C874_NPADVERTISE 0x07 /* Auto-negotiation next page advertisement */ #define MII_AM79C874_MISCFEATURES 0x10 /* Miscellaneous features reg */ #define MII_AM79C874_INTCS 0x11 /* Interrupt control/status */ @@ -91,6 +97,7 @@ /* Luminary LM3S6918 built-in PHY: 0x07-0x0f, 0x14-0x16, 0x19-0x1f reserved */ +#define MII_LM3S6918_NAME "LM3S6918" #define MII_LM_VSPECIFIC 0x10 /* Vendor-Specific */ #define MII_LM_INTCS 0x11 /* Interrupt control/status */ #define MII_LM_DIAGNOSTIC 0x12 /* Diagnostic */ @@ -100,12 +107,14 @@ /* Micrel KS8721: 0x15, 0x1b, and 0x1f */ +#define MII_KS8721_NAME "KS8721" #define MII_KS8721_RXERCOUNTER 0x15 /* RXER counter */ #define MII_KS8721_INTCS 0x1b /* Interrupt control/status register */ #define MII_KS8721_10BTCR 0x1f /* 10BASE-TX PHY control register */ /* Micrel KSZ8041: 0x15, 0x1b, 0x1e-0x1f */ +#define MII_KSZ8041_NAME "KSZ8041" #define MII_KSZ8041_RXERR 0x15 /* RXERR Counter */ #define MII_KSZ8041_INT 0x1b /* Interrupt Control/Status */ #define MII_KSZ8041_PHYCTRL1 0x1e /* PHY Control 1 */ @@ -113,6 +122,7 @@ /* Micrel KSZ8051: 0x11, 0x15-0x18, 0x1b, 0x1d-0x1f */ +#define MII_KSZ8051_NAME "KSZ8051" #define MII_KSZ8051_AFEC1 0x11 /* AFE Control 1 */ #define MII_KSZ8051_RXERR 0x15 /* RXERR Counter */ #define MII_KSZ8051_OMSO 0x16 /* Operation Mode Strap Override */ @@ -124,6 +134,8 @@ #define MII_KSZ8051_PHYCTRL2 0x1f /* PHY Control 2 */ /* Micrel KSZ8061: 0x10-0x18, 0x1b, 0x1c-0x1f */ + +#define MII_KSZ8061_NAME "KSZ8061" #define MII_KSZ8061_DIG_CTRL 0x10 /* Digital Control */ #define MII_KSZ8061_AFE_CTRL_0 0x11 /* AFE Control 0 */ #define MII_KSZ8061_AFE_CTRL_1 0x12 /* AFE Control 1 */ @@ -141,6 +153,7 @@ /* Micrel KSZ8081: 0x10-0x11, 0x15-0x18, 0x1b, 0x1d-0x1f */ +#define MII_KSZ8081_NAME "KSZ8081" #define MII_KSZ8081_DRCTRL 0x10 /* Digital Reserve Control */ #define MII_KSZ8081_AFEC1 0x11 /* AFE Control 1 */ #define MII_KSZ8081_RXERR 0x15 /* RXERR Counter */ @@ -156,6 +169,7 @@ * 0x8-0x15, 0x13, 0x1c reserved */ +#define MII_DP83848C_NAME "DP83848C" #define MII_DP83848C_STS 0x10 /* RO PHY Status Register */ #define MII_DP83848C_MICR 0x11 /* RW MII Interrupt Control Register */ #define MII_DP83848C_MISR 0x12 /* RO MII Interrupt Status Register */ @@ -171,6 +185,7 @@ /* Texas Instruments DP83825I PHY Extended Registers. */ +#define MII_DP83825I_NAME "DP83825I" #define MII_DP83825I_PHYSTS 0x10 /* RO PHY Status Register */ #define MII_DP83825I_PHYSCR 0x11 /* RW PHY Specific Control Register */ #define MII_DP83825I_MISR1 0x12 /* RO MII Interrupt Status Register 1 */ @@ -189,6 +204,7 @@ /* SMSC LAN8720 PHY Extended Registers */ +#define MII_LAN8720_NAME "LAN8720" #define MII_LAN8720_REV 0x10 /* Silicon Revision Register */ #define MII_LAN8720_MCSR 0x11 /* Mode Control/Status Register */ #define MII_LAN8720_MODES 0x12 /* Special modes */ @@ -201,6 +217,8 @@ /* SMSC LAN8740/LAN8742A PHY Extended Registers */ +#define MII_LAN8740_NAME "LAN8740" +#define MII_LAN8742A_NAME "LAN8742A" #define MII_LAN8740_CONFIG 0x10 /* EDPD NDL/Crossover Timer/EEE Configuration */ #define MII_LAN8740_MCSR 0x11 /* Mode Control/Status Register */ #define MII_LAN8740_MODES 0x12 /* Special modes */ @@ -215,6 +233,7 @@ /* Motorcomm YT8512C/YT8512H Extended Registers */ +#define MII_YT8512_NAME "YT8512" #define MII_YT8512_PHYSFC 0x10 /* PHY Function conrtol Register */ #define MII_YT8512_PHYSTS 0x11 /* PHY Status Register */ #define MII_YT8512_IMR 0x12 /* Interrupt Mask Register */ @@ -728,12 +747,15 @@ /* TJA110X MII ID1/2 register bits */ +#define MII_TJA1100_NAME "TJA1100" #define MII_PHYID1_TJA1100 0x0180 /* ID1 value for NXP TJA1100 */ #define MII_PHYID2_TJA1100 0xdc40 /* ID2 value for NXP TJA1100 */ +#define MII_TJA1101_NAME "TJA1101" #define MII_PHYID1_TJA1101 0x0180 /* ID1 value for NXP TJA1101 */ #define MII_PHYID2_TJA1101 0xdd00 /* ID2 value for NXP TJA1101 */ +#define MII_TJA1103_NAME "TJA1103" #define MII_PHYID1_TJA1103 0x01b /* ID1 value for NXP TJA1103 */ #define MII_PHYID2_TJA1103 0xB013 /* ID2 value for NXP TJA1103 */ @@ -915,6 +937,22 @@ * Type Definitions ****************************************************************************/ +struct phy_desc_s +{ + char name[16]; /* The name of the PHY */ + uint16_t id1; /* The MII_PHYID1 registers value */ + uint16_t id2; /* The MII_PHYID2 registers value */ + uint16_t status; /* The Phys status register or 0xffff */ + uint16_t address_lo; /* The lowest address to check for the PHY */ + uint16_t address_high; /* The highest address to check for the PHY or + * 0xffff uses only the address_lo (one address) + */ + uint16_t mbps10; /* The bit mask for 10MBP if status is not 0xffff */ + uint16_t mbps100; /* The bit mask for 100MBP if status is not 0xffff */ + uint16_t duplex; /* The bit mask for DUPLEX if status is not 0xffff */ + uint16_t clause; /* The PHY clause supported. 22 or 45 */ +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -932,4 +970,5 @@ extern "C" } #endif +#endif /* __ASSEMBLY__ */ #endif /* __INCLUDE_NUTTX_NET_MII_H */ diff --git a/libs/libc/machine/risc-v/arch_elf.c b/libs/libc/machine/risc-v/arch_elf.c index 1fe174d307eb1..c64e2c8548e48 100644 --- a/libs/libc/machine/risc-v/arch_elf.c +++ b/libs/libc/machine/risc-v/arch_elf.c @@ -154,25 +154,24 @@ static void _add_val(uint16_t *addr, uint32_t val) static void _calc_imm(long offset, long *imm_hi, long *imm_lo) { - long lo; - long hi = offset / 4096; - long r = offset % 4096; + long hi = offset / 0x1000; + long lo = offset - hi * 0x1000; - if (2047 < r) + if (0x7ff < lo) { hi++; + lo -= 0x1000; } - else if (r < -2048) + else if (lo < -0x800) { hi--; + lo += 0x1000; } - lo = offset - (hi * 4096); - binfo("offset=%ld: hi=%ld lo=%ld\n", offset, hi, lo); - ASSERT(-2048 <= lo && lo <= 2047); + ASSERT(-0x800 <= lo && lo <= 0x7ff); *imm_lo = lo; *imm_hi = hi; diff --git a/net/can/can_callback.c b/net/can/can_callback.c index d8ebfc65506ef..2804b67d1ba67 100644 --- a/net/can/can_callback.c +++ b/net/can/can_callback.c @@ -65,6 +65,10 @@ can_data_event(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn, uint16_t recvlen; uint16_t ret; +#ifdef CONFIG_NET_TIMESTAMP + buflen -= sizeof(struct timeval); +#endif + ret = (flags & ~CAN_NEWDATA); /* Save as the packet data as in the read-ahead buffer. NOTE that @@ -214,11 +218,16 @@ uint16_t can_datahandler(FAR struct net_driver_s *dev, can_readahead_signal(conn); #endif ret = iob->io_pktlen; - } - /* Device buffer must be enqueue or freed, clear the handle */ + /* Device buffer has been enqueued, clear the handle */ - netdev_iob_clear(dev); + netdev_iob_clear(dev); + } + else + { + nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret); + netdev_iob_release(dev); + } return ret; } diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c index f7dc4e459eb3a..4ce63b69ee751 100644 --- a/net/can/can_recvmsg.c +++ b/net/can/can_recvmsg.c @@ -233,7 +233,7 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) pstate->pr_recvlen = -1; - if ((iob = iob_peek_queue(&conn->readahead)) != NULL && + if ((iob = iob_remove_queue(&conn->readahead)) != NULL && pstate->pr_buflen > 0) { DEBUGASSERT(iob->io_pktlen > 0); @@ -246,17 +246,7 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) if (can_recv_filter(conn, can_id) == 0) { - FAR struct iob_s *tmp; - - /* Remove the I/O buffer chain from the head of the read-ahead - * buffer queue. - */ - - tmp = iob_remove_queue(&conn->readahead); - DEBUGASSERT(tmp == iob); - UNUSED(tmp); - - /* And free the I/O buffer chain */ + /* Free the I/O buffer chain */ iob_free_chain(iob); return 0; @@ -277,37 +267,16 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) recvlen = iob_copyout(pstate->pr_buffer, iob, pstate->pr_buflen, 0); - /* If we took all of the data from the I/O buffer chain is empty, then - * release it. If there is still data available in the I/O buffer - * chain, then just trim the data that we have taken from the - * beginning of the I/O buffer chain. + /* We should have taken all of the data from the I/O buffer chain, + * so release it. There is no trimming needed, since One CAN/CANFD + * frame can always fit in one IOB. */ - if (recvlen >= iob->io_pktlen) - { - FAR struct iob_s *tmp; - - /* Remove the I/O buffer chain from the head of the read-ahead - * buffer queue. - */ - - tmp = iob_remove_queue(&conn->readahead); - DEBUGASSERT(tmp == iob); - UNUSED(tmp); + static_assert(sizeof(struct can_frame) <= CONFIG_IOB_BUFSIZE); - /* And free the I/O buffer chain */ + /* Free the I/O buffer chain */ - iob_free_chain(iob); - } - else - { - /* The bytes that we have received from the head of the I/O - * buffer chain (probably changing the head of the I/O - * buffer queue). - */ - - iob_trimhead_queue(&conn->readahead, recvlen); - } + iob_free_chain(iob); /* do not pass frames with DLC > 8 to a legacy socket */ #if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) diff --git a/net/devif/devif_send.c b/net/devif/devif_send.c index 943b737bbdba4..15ec735f7cfbf 100644 --- a/net/devif/devif_send.c +++ b/net/devif/devif_send.c @@ -102,7 +102,12 @@ int devif_send(FAR struct net_driver_s *dev, FAR const void *buf, /* Prepare device buffer before poll callback */ - iob_update_pktlen(dev->d_iob, offset, false); + /* if pktlen is 0, no need to update */ + + if (offset != 0) + { + iob_update_pktlen(dev->d_iob, offset, false); + } ret = iob_trycopyin(dev->d_iob, buf, len, offset, false); if (ret != len) diff --git a/openamp/0003-libmetal-nuttx-io.c-Fix-void-pointer-arithmetic-in-a.patch b/openamp/0003-libmetal-nuttx-io.c-Fix-void-pointer-arithmetic-in-a.patch new file mode 100644 index 0000000000000..88ce403c93f8c --- /dev/null +++ b/openamp/0003-libmetal-nuttx-io.c-Fix-void-pointer-arithmetic-in-a.patch @@ -0,0 +1,36 @@ +From 59e2764f9d0598ad0135286d4a0ee1ac95893bba Mon Sep 17 00:00:00 2001 +From: Jukka Laitinen +Date: Mon, 12 Feb 2024 13:27:13 +0200 +Subject: [PATCH] libmetal/nuttx/io.c: Fix void pointer arithmetic in access + alignment + +Signed-off-by: Jukka Laitinen +--- + libmetal/lib/system/nuttx/io.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/system/nuttx/io.c libmetal/lib/system/nuttx/io.c +index 3ce9cbe..ab9bc6a 100644 +--- a/lib/system/nuttx/io.c ++++ libmetal/lib/system/nuttx/io.c +@@ -45,7 +45,7 @@ static int metal_io_block_read_(struct metal_io_region *io, + *(uint32_t *)dst = *(uint32_t *)va; + else if (len == 8) { + *(uint32_t *)dst = *(uint32_t *)va; +- *(uint32_t *)(dst + 4) = *(uint32_t *)(va + 4); ++ *((uint32_t *)dst + 1) = *((uint32_t *)va + 1); + } else + memcpy(dst, va, len); + +@@ -68,7 +68,7 @@ static int metal_io_block_write_(struct metal_io_region *io, + *(uint32_t *)va = *(uint32_t *)src; + else if (len == 8) { + *(uint32_t *)va = *(uint32_t *)src; +- *(uint32_t *)(va + 4) = *(uint32_t *)(src + 4); ++ *((uint32_t *)va + 1) = *((uint32_t *)src + 1); + } else + memcpy(va, src, len); + +-- +2.34.1 + diff --git a/openamp/libmetal.defs b/openamp/libmetal.defs index b3369496abe8c..90e8a690bee8c 100644 --- a/openamp/libmetal.defs +++ b/openamp/libmetal.defs @@ -79,6 +79,7 @@ libmetal.zip: $(Q) mv libmetal-$(VERSION) libmetal $(Q) patch -p0 < 0001-libmetal-add-metal_list_for_each_safe-support.patch $(Q) patch -p0 < 0002-libmetal-nuttx-io.c-align-access-when-read-write-siz.patch + $(Q) patch -p0 < 0003-libmetal-nuttx-io.c-Fix-void-pointer-arithmetic-in-a.patch .libmetal_headers: libmetal.zip else diff --git a/sched/group/group_killchildren.c b/sched/group/group_killchildren.c index bafe734071979..331ae3dddb0d9 100644 --- a/sched/group/group_killchildren.c +++ b/sched/group/group_killchildren.c @@ -181,29 +181,33 @@ int group_kill_children(FAR struct tcb_s *tcb) #if defined(CONFIG_GROUP_KILL_CHILDREN_TIMEOUT_MS) && \ CONFIG_GROUP_KILL_CHILDREN_TIMEOUT_MS != 0 - /* Send SIGTERM for each first */ - group_foreachchild(tcb->group, group_kill_children_handler, - (FAR void *)((uintptr_t)tcb->pid)); + if ((tcb->flags & TCB_FLAG_FORCED_CANCEL) == 0) + { + /* Send SIGTERM for each first */ - /* Wait a bit for child exit */ + group_foreachchild(tcb->group, group_kill_children_handler, + (FAR void *)((uintptr_t)tcb->pid)); - ret = CONFIG_GROUP_KILL_CHILDREN_TIMEOUT_MS; - while (1) - { - if (tcb->group->tg_nmembers <= 1) + /* Wait a bit for child exit */ + + ret = CONFIG_GROUP_KILL_CHILDREN_TIMEOUT_MS; + while (1) { - break; - } + if (tcb->group->tg_nmembers <= 1) + { + break; + } - nxsig_usleep(USEC_PER_MSEC); + nxsig_usleep(USEC_PER_MSEC); # if CONFIG_GROUP_KILL_CHILDREN_TIMEOUT_MS > 0 - if (--ret < 0) - { - break; - } + if (--ret < 0) + { + break; + } # endif + } } #endif diff --git a/tools/ci/cibuild.sh b/tools/ci/cibuild.sh index c2120f6dcb574..980628c1ca7f5 100755 --- a/tools/ci/cibuild.sh +++ b/tools/ci/cibuild.sh @@ -116,7 +116,7 @@ function avr-gcc-toolchain { brew install avr-gcc ;; Linux) - apt-get install -y avr-libc gcc-avr + sudo apt-get install -y avr-libc gcc-avr ;; esac fi @@ -187,7 +187,7 @@ function clang-tidy { if ! type clang-tidy &> /dev/null; then case ${os} in Linux) - apt-get install -y clang clang-tidy + sudo apt-get install -y clang clang-tidy ;; esac fi @@ -215,7 +215,7 @@ function util-linux { brew install flock ;; Linux) - apt-get install -y util-linux + sudo apt-get install -y util-linux ;; esac fi @@ -231,7 +231,7 @@ function gen-romfs { brew install genromfs ;; Linux) - apt-get install -y genromfs + sudo apt-get install -y genromfs ;; esac fi @@ -467,7 +467,7 @@ function u-boot-tools { brew install u-boot-tools ;; Linux) - apt-get install -y u-boot-tools + sudo apt-get install -y u-boot-tools ;; esac fi @@ -588,7 +588,7 @@ case ${os} in rm -f /usr/local/bin/openssl || : ;; Linux) - install="arm-clang-toolchain arm-gcc-toolchain arm64-gcc-toolchain avr-gcc-toolchain binutils bloaty clang-tidy gen-romfs gperf kconfig-frontends mips-gcc-toolchain python-tools riscv-gcc-toolchain rust rx-gcc-toolchain sparc-gcc-toolchain xtensa-esp32-gcc-toolchain u-boot-tools util-linux wasi-sdk c-cache" + install="arm-gcc-toolchain binutils gen-romfs gperf kconfig-frontends python-tools riscv-gcc-toolchain c-cache" ;; esac diff --git a/tools/ci/testlist/ssrc-arm.dat b/tools/ci/testlist/ssrc-arm.dat new file mode 100644 index 0000000000000..215a99582a7ca --- /dev/null +++ b/tools/ci/testlist/ssrc-arm.dat @@ -0,0 +1,2 @@ +/arm/stm32f7,CONFIG_ARM_TOOLCHAIN_GNU_EABI + diff --git a/tools/ci/testlist/ssrc-riscv.dat b/tools/ci/testlist/ssrc-riscv.dat new file mode 100644 index 0000000000000..d8becf48b6e83 --- /dev/null +++ b/tools/ci/testlist/ssrc-riscv.dat @@ -0,0 +1,2 @@ +/risc-v/mpfs +