diff --git a/.circleci/config.yml b/.circleci/config.yml index b587f4e7..1a42f60a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ exec: &exec name: build-tools/nerves-system-br - version: 1.20.3 - elixir: 1.13.4-otp-25 + version: 1.27.1 + elixir: 1.16.2-otp-26 version: 2.1 orbs: - build-tools: nerves-project/build-tools@0.2.2 + build-tools: nerves-project/build-tools@0.2.3 workflows: version: 2 @@ -29,12 +29,6 @@ workflows: filters: tags: only: /.*/ - - build-tools/build-test: - exec: - <<: *exec - context: nerves-global - requires: - - build-tools/build-system - build-tools/deploy-system: exec: <<: *exec diff --git a/.tool-versions b/.tool-versions index 6d5c8116..68aaa634 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -elixir 1.13.4-otp-25 -erlang 25.0.3 +elixir 1.14.4-otp-26 +erlang 26.2.4 diff --git a/CHANGELOG.md b/CHANGELOG.md index f913edd5..86767d60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,204 @@ follows: releases, and Linux kernel updates. They're also made to fix bugs and add features to the build infrastructure. +## v2.22.0 + +This is a major Buildroot update. + +Please see the [nerves_system_br v1.27.0 release notes](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.26.0) +for upgrade instructions if you've forked this system. + +* Updated dependencies + * Linux 6.6.15-ti-arm32-r1 + * [nerves_system_br v1.27.0](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.27.0) + * [Buildroot 2024.02](https://lore.kernel.org/buildroot/87msrczp4z.fsf@48ers.dk/) + * [Erlang/OTP 26.2.3](https://erlang.org/download/OTP-26.2.3.README) + +## v2.21.0 + +This is a major Buildroot and Linux update. If you use `circuits_gpio`, it is +critical to update to 1.2.0 or later to get a workaround for GPIO indices +changing. + +Please see the [nerves_system_br v1.26.0 release notes](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.26.0) +for upgrade instructions if you've forked this system. + +* Updated dependencies + * linux 6.1.69-ti-r21 + * [Erlang/OTP 26.2.2](https://erlang.org/download/OTP-26.2.2.README) + * [nerves_system_br v1.26.1](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.26.1) + * [Buildroot 2023.11.1](https://lore.kernel.org/buildroot/87cyu2k2gu.fsf@48ers.dk/T/) + +## v2.20.2 + +This is a security/bug fix update. + +* Package updates + * [Erlang/OTP 26.2.1](https://erlang.org/download/OTP-26.2.1.README) + * [nerves_heart 2.3.0](https://github.com/nerves-project/nerves_heart/releases/tag/v2.3.0) + +## v2.20.1 + +This fixes a regression where the forced `circuits_gpio` dependency update broke +compilation. This removes the optional dependency, but be sure to see the note +below about the GPIOs being remapped and Circuits.GPIO v1.2.0 containing a +workaround. + +## v2.20.0 + +This is a major Buildroot, toolchain, and Linux kernel update. + +Please see [nerves_system_br v1.25.0 release notes](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.25.0) +for upgrade instructions if you've forked this system. + +The Linux kernel update from 5.10 to 6.1 has a side effect of renumbering GPIOs. +Circuits.GPIO v1.2 accounts for this so programs don't need to change that use +it. See https://github.com/elixir-circuits/circuits_gpio/pull/153 for more +information. This system has an optional dependency on Circuits.GPIO to force +the upgrade. + +* Updated dependencies + * Linux 6.1.46-ti-r13 + * [nerves_system_br v1.25.2](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.25.2) + * [Buildroot 2023.08.4](https://lore.kernel.org/buildroot/87o7f6t7fs.fsf@48ers.dk/T/) + * [Erlang/OTP 26.1.2](https://erlang.org/download/OTP-26.1.2.README) + +## v2.19.1 + +This is a security/bug fix update. + +* Package updates + * [nerves_system_br v1.24.1](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.24.1) + * [Erlang/OTP 26.1.1](https://erlang.org/download/OTP-26.1.1.README) + * [Buildroot 2023.05.3](https://lore.kernel.org/buildroot/87h6ngup34.fsf@48ers.dk/T/) + +## v2.19.0 + +This is a Buildroot version update that appears to mostly contain bug and +security fixes. It should be a low risk upgrade from v2.18.2. + +* New features + * Support factory reset, preventing firmware reverts. See [Nerves.Runtime.FwupOps](https://hexdocs.pm/nerves_runtime/Nerves.Runtime.FwupOps.html) + +* Updated dependencies + * [nerves_system_br v1.24.0](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.24.0) + * [Buildroot 2023.05.2](https://lore.kernel.org/buildroot/87ledrkrpp.fsf@48ers.dk/T/), [2023.05.1](https://lore.kernel.org/buildroot/87351m8qm4.fsf@48ers.dk/T/), [2023.05](https://lore.kernel.org/buildroot/87r0qn2c77.fsf@48ers.dk/T/) + * [Erlang/OTP 26.1](https://erlang.org/download/OTP-26.1.README) + +## v2.18.2 + +* Updated dependencies + * [nerves_system_br v1.23.3](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.23.3) + +## v2.18.1 + +This is a bug and security fix update. It should be a low risk upgrade. + +* Fixes + * Fix CTRL+R over ssh + +* Updated dependencies + * [nerves_system_br v1.23.2](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.23.2) + * [Buildroot 2023.02.2](https://lore.kernel.org/buildroot/87y1je6wva.fsf@48ers.dk/T/) + +## v2.18.0 + +This is a major update that brings in Erlang/OTP 26, Buildroot 2023.02.2 and +Linux 5.10.162. + +* New features + * CA certificates are included for OTP 26. + +* Updated dependencies + * [nerves_system_br v1.23.1](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.23.1) + * [Buildroot 2023.02.2](https://lore.kernel.org/buildroot/87wn03ifbl.fsf@48ers.dk/T/) + * [Erlang/OTP 26.0.2](https://erlang.org/download/OTP-26.0.2.README) + * Linux 5.10.162 + +## v2.17.2 + +This is a bug and security fix update. It should be a low risk upgrade. + +* Updated dependencies + * [nerves_system_br v1.22.5](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.22.5) + * [Buildroot 2022.11.3](https://lore.kernel.org/buildroot/878rfuxbxx.fsf@dell.be.48ers.dk/T/) + +## v2.17.1 + +This is a bug fix and Erlang version bump from 25.2 to 25.2.3. It should be a +low risk upgrade. + +* Fixes + * Set Erlang crash dump timer to 5 seconds, so if an Erlang crash dump does + happen, it will run for at most 5 seconds. See erlinit.conf. + +* Updated dependencies + * [nerves_system_br v1.22.3](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.22.3) + * [Buildroot 2022.11.1](https://lore.kernel.org/buildroot/87ilh4dvax.fsf@dell.be.48ers.dk/T/#u) + +## v2.17.0 + +This is a Buildroot version update that appears to mostly contain bug and +security fixes. It should be a low risk upgrade. + +* Updated dependencies + * [nerves_system_br v1.22.1](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.22.1) + * [Buildroot 2022.11](http://lists.busybox.net/pipermail/buildroot/2022-December/656980.html) + * GCC 12.2 + +## v2.16.2 + +* Changes + * Two Buildroot patch updates and an Erlang minor version update + * Nerves Heart v2.0 is now included. Nerves Heart connects the Erlang runtime + to a hardware watchdog. v2.0 has numerous updates to improve information + that you can get and also has more safeguards to avoid conditions that could + cause a device to hang forever. + +* Updated dependencies + * [nerves_system_br v1.21.6](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.21.6) + * [Erlang/OTP 25.2](https://erlang.org/download/OTP-25.2.README) + * [Buildroot 2022.08.3](https://lore.kernel.org/buildroot/87r0x7z5cw.fsf@dell.be.48ers.dk/T/#u) + * [nerves_heart v2.0.2](https://github.com/nerves-project/nerves_heart/releases/tag/v2.0.2) + +## v2.16.1 + +* Changes + * Reduce first-time Linux kernel download by using tarball source + +* Updated dependencies + * [nerves_system_br v1.21.2](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.21.2) + * [Erlang/OTP 25.1.2](https://erlang.org/download/OTP-25.1.2.README) + +## v2.16.0 + +* Changes + * Support aarch64 Linux builds + * Add libdtc to support runtime loading of device tree overlays + +* Updated dependencies + * [nerves_system_br v1.21.1](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.21.1) + and also see [nerves_system_br v1.21.0](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.21.0) + * [Buildroot 2022.08.1](http://lists.busybox.net/pipermail/buildroot/2022-October/652816.html) + * [Erlang/OTP 25.1.1](https://erlang.org/download/OTP-25.1.1.README) + +## v2.15.3 + +* Fixes + * Allow kernel includes for device tree overlays (Thanks @insasec) + +* Updated dependencies + * [nerves_system_br v1.20.6](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.20.6) + * [Erlang/OTP 25.0.4](https://erlang.org/download/OTP-25.0.4.README) + * [Buildroot 2022.05.2](http://lists.busybox.net/pipermail/buildroot/2022-August/650546.html) + * Also see [Buildroot 2022.05.1 changes](http://lists.busybox.net/pipermail/buildroot/2022-July/647814.html) + +## v2.15.2 + +* Updated dependencies + * [nerves_system_br v1.20.4](https://github.com/nerves-project/nerves_system_br/releases/tag/v1.20.4) + * [Erlang/OTP 25.0.3](https://erlang.org/download/OTP-25.0.3.README) + ## v2.15.1 This release reverts the upgrade to Linux 5.15.44. The Linux kernel is now at diff --git a/README.md b/README.md index 7fbbedf4..94d32426 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ and [PocketBeagle](https://beagleboard.org/pocket). | CPU | 1 GHz ARM Cortex-A8 | | Memory | 512 MB DRAM | | Storage | 4 GB eMMC Flash and MicroSD | -| Linux kernel | 5.10 w/ BBB patches | +| Linux kernel | 6.6 w/ "ti" patches | | IEx terminal | UART `ttyS0` | | GPIO, I2C, SPI | Yes - [Elixir Circuits](https://github.com/elixir-circuits) | | ADC | Yes | @@ -269,20 +269,6 @@ configure WiFi for your device. At a shell prompt, run `lsmod` to see which drivers are loaded. Running `dmesg` may also give a clue. When using `dmesg`, reinsert the USB dongle to generate new log messages if you don't see them. -## Beaglebone Green WiFi - -Initial support for the BBGW's onboard wireless module is available. To try it -out, run (assuming you have VintageNet in your image): - -```elixir -:os.cmd('modprobe wl18xx') -:os.cmd('modprobe wlcore_sdio') -VintageNetWiFi.quick_configure("ssid", "password") -``` - -Be aware that this Nerves system does not configure the MAC address. The result -is that only one BBGW may exist on the WiFi network at a time. - ## Bluetooth The Beaglebone boards with built-in WiFi support use the WiLink8 WL1835 module. diff --git a/VERSION b/VERSION index 6030c9fc..d7afd714 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.15.1+zola-9 +2.22.0+zola-1 diff --git a/fwup-revert.conf b/fwup-ops.conf similarity index 57% rename from fwup-revert.conf rename to fwup-ops.conf index 5e03feaa..daf5e335 100644 --- a/fwup-revert.conf +++ b/fwup-ops.conf @@ -1,13 +1,21 @@ -# Revert firmware on the Beaglebone Black +# Post-installation firmware operations for the Beaglebone Black +# +# Tasks include: +# +# * `factory-reset` - Clear out the writable filesystem and any other writable +# areas so that they can be re-initialized on the next boot. +# * `prevent-revert` - Prevent `revert` from working until the next firmware +# * `revert` - Revert to the previous firmware if it's still available +# * `validate` - Mark this firmware as a good update. +# * `status` - Print out which partition is active (`a` or `b`) # # To use: -# 1. Run `fwup -c -f fwup-revert.conf -o revert.fw` and copy revert.fw to -# the device. This is done automatically as part of the Nerves system -# build process. The file is stored in `/usr/share/fwup/revert.fw`. -# 2. On the device, run `fwup -t revert revert.fw -d $NERVES_FW_DEVPATH`. If -# it succeeds, reboot. If not, then it's possible that there isn't a previous -# firmware or the metadata about what's stored where is corrupt or out of -# sync. +# +# 1. Run `fwup -c -f fwup-ops.conf -o ops.fw` and copy ops.fw to +# the device. This is done automatically as part of the Nerves system +# build process. The file is stored in `/usr/share/fwup/ops.fw`. +# 2. On the device, run `fwup -t -d /dev/rootdisk0 --enable-trim /usr/share/fwup/ops.fw`. +# 3. Reboot after running `revert` or `factory-reset`. # # It is critical that this is kept in sync with the main fwup.conf. @@ -56,6 +64,22 @@ define(NERVES_FW_AUTHOR, "The Zola Team") define(UBOOT_ENV_OFFSET, 2048) define(UBOOT_ENV_COUNT, 256) # 128 KB +# The boot partition contains MLO, u-boot.img, and zImage +define(BOOT_PART_OFFSET, 4096) +define(BOOT_PART_COUNT, 28672) + +# Let the rootfs have room to grow up to 140 MiB and align it to the nearest 1 +# MB boundary +define(ROOTFS_A_PART_OFFSET, 63488) +define(ROOTFS_A_PART_COUNT, 286720) +define-eval(ROOTFS_B_PART_OFFSET, "${ROOTFS_A_PART_OFFSET} + ${ROOTFS_A_PART_COUNT}") +define(ROOTFS_B_PART_COUNT, ${ROOTFS_A_PART_COUNT}) + +# Application partition. This partition can occupy all of the remaining space. +# Size it to fit the destination. +define-eval(APP_PART_OFFSET, "${ROOTFS_B_PART_OFFSET} + ${ROOTFS_B_PART_COUNT}") +define(APP_PART_COUNT, 1048576) + # Firmware archive metadata meta-product = ${NERVES_FW_PRODUCT} meta-description = ${NERVES_FW_DESCRIPTION} @@ -72,6 +96,60 @@ uboot-environment uboot-env { block-count = ${UBOOT_ENV_COUNT} } +## +# factory-reset +## +task factory-reset { + on-init { + info("Erasing all writable data") + # This requires --enable-trim + trim(${APP_PART_OFFSET}, ${APP_PART_COUNT}) + raw_memset(${APP_PART_OFFSET}, 256, 0xff) + } +} + +## +# prevent-revert +# +# Pass `--enable-trim` to also clear out the partition that no longer should be used. +## +task prevent-revert.a { + # Check that we're running on B + require-uboot-variable(uboot-env, "nerves_fw_active", "b") + + on-init { + info("Preventing reverts to partition A") + # Remove U-Boot variables that fwup uses to allow reverting images + uboot_unsetenv(uboot-env, "a.nerves_fw_platform") + uboot_unsetenv(uboot-env, "a.nerves_fw_architecture") + # Clear out the old image using TRIM. This requires --enable-trim + trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT}) + fat_rm(${BOOT_PART_OFFSET}, "zImage.a") + } +} +task prevent-revert.b { + # Check that we're running on A + require-uboot-variable(uboot-env, "nerves_fw_active", "a") + + on-init { + info("Preventing reverts to partition B") + # Remove U-Boot variables that fwup uses to allow reverting images + uboot_unsetenv(uboot-env, "b.nerves_fw_platform") + uboot_unsetenv(uboot-env, "b.nerves_fw_architecture") + # Clear out the old image using TRIM. This requires --enable-trim + trim(${ROOTFS_B_PART_OFFSET}, ${ROOTFS_B_PART_COUNT}) + fat_rm(${BOOT_PART_OFFSET}, "zImage.b") + } +} +task prevent-revert.fail { + on-init { + error("Error detecting active partition") + } +} + +## +# revert +## task revert.a { # This task reverts to the A partition, so check that we're running on B require-uboot-variable(uboot-env, "nerves_fw_active", "b") @@ -129,7 +207,11 @@ task revert.wrongplatform { } } -# Run "fwup /usr/share/fwup/revert.fw -t status -d /dev/mmcblk0 -q -U" to check the status. +## +# status +# +# Run "fwup /usr/share/fwup/ops.fw -t status -d /dev/rootdisk0 -q -U" to check the status. +## task status.aa { require-path-on-device("/", "/dev/mmcblk1p2") require-uboot-variable(uboot-env, "nerves_fw_active", "a") @@ -153,3 +235,15 @@ task status.ba { task status.fail { on-init { error("fail") } } + +## +# validate +## +task validate { + on-init { + info("Validate") + uboot_setenv(uboot-env, "nerves_fw_validated", "1") + uboot_setenv(uboot-env, "upgrade_available", "0") + uboot_setenv(uboot-env, "bootcount", "1") + } +} diff --git a/linux/0001-rcn-linux-6.6.15-ti-arm32-r1.patch b/linux/0001-rcn-linux-6.6.15-ti-arm32-r1.patch new file mode 100644 index 00000000..e9e54432 --- /dev/null +++ b/linux/0001-rcn-linux-6.6.15-ti-arm32-r1.patch @@ -0,0 +1,71316 @@ +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-clocks.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-clocks.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-clocks.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-clocks.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Device Tree Source for Keystone 2 clock tree + * +- * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2013-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + clocks { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone.dtsi b/arch/arm/boot/dts/ti/keystone/keystone.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2013-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2e-clocks.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2e-clocks.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2e-clocks.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2e-clocks.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 Edison SoC specific device tree + * +- * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2014-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + clocks { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2e.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2e.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2e.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2e.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 Edison soc device tree + * +- * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2013-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2e-evm.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2e-evm.dts +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2e-evm.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2e-evm.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 Edison EVM device tree + * +- * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2013-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + /dts-v1/; + +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2e-netcp.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2e-netcp.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2e-netcp.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2e-netcp.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Device Tree Source for Keystone 2 Edison Netcp driver + * +- * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + qmss: qmss@2a40000 { +@@ -36,9 +36,9 @@ + qpend { + qpend-0 { + qrange = <658 8>; +- interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04 +- 0 43 0xf04 0 44 0xf04 0 45 0xf04 +- 0 46 0xf04 0 47 0xf04>; ++ interrupts = <0 40 0xf04 0 41 0xf04 0 42 0xf04 ++ 0 43 0xf04 0 44 0xf04 0 45 0xf04 ++ 0 46 0xf04 0 47 0xf04>; + }; + qpend-1 { + qrange = <528 16>; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2g.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2g.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2g.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2g.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Device Tree Source for K2G SOC + * +- * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2g-evm.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2g-evm.dts +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2g-evm.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2g-evm.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -2,14 +2,14 @@ + /* + * Device Tree Source for K2G EVM + * +- * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2016-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + /dts-v1/; + + #include "keystone-k2g.dtsi" + + / { +- compatible = "ti,k2g-evm", "ti,k2g", "ti,keystone"; ++ compatible = "ti,k2g-evm", "ti,k2g", "ti,keystone"; + model = "Texas Instruments K2G General Purpose EVM"; + + memory@800000000 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2g-ice.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2g-ice.dts +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2g-ice.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2g-ice.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Device Tree Source for K2G Industrial Communication Engine EVM + * +- * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + /dts-v1/; + +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2g-netcp.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2g-netcp.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2g-netcp.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2g-netcp.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Device Tree Source for K2G Netcp driver + * +- * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/ + */ + + qmss: qmss@4020000 { +@@ -37,9 +37,9 @@ + qpend { + qpend-0 { + qrange = <77 8>; +- interrupts =<0 308 0xf04 0 309 0xf04 0 310 0xf04 +- 0 311 0xf04 0 312 0xf04 0 313 0xf04 +- 0 314 0xf04 0 315 0xf04>; ++ interrupts = <0 308 0xf04 0 309 0xf04 0 310 0xf04 ++ 0 311 0xf04 0 312 0xf04 0 313 0xf04 ++ 0 314 0xf04 0 315 0xf04>; + qalloc-by-id; + }; + }; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2hk-clocks.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-clocks.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2hk-clocks.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-clocks.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 Kepler/Hawking SoC clock nodes + * +- * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2013-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + clocks { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2hk.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2hk.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2hk.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2hk.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 Kepler/Hawking soc specific device tree + * +- * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2013-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2hk-evm.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-evm.dts +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2hk-evm.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-evm.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 Kepler/Hawking EVM device tree + * +- * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2013-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + /dts-v1/; + +@@ -10,7 +10,7 @@ + #include "keystone-k2hk.dtsi" + + / { +- compatible = "ti,k2hk-evm", "ti,k2hk", "ti,keystone"; ++ compatible = "ti,k2hk-evm", "ti,k2hk", "ti,keystone"; + model = "Texas Instruments Keystone 2 Kepler/Hawking EVM"; + + reserved-memory { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2hk-netcp.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-netcp.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2hk-netcp.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2hk-netcp.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Device Tree Source for Keystone 2 Hawking Netcp driver + * +- * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + qmss: qmss@2a40000 { +@@ -49,9 +49,9 @@ + qpend { + qpend-0 { + qrange = <658 8>; +- interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04 +- 0 43 0xf04 0 44 0xf04 0 45 0xf04 +- 0 46 0xf04 0 47 0xf04>; ++ interrupts = <0 40 0xf04 0 41 0xf04 0 42 0xf04 ++ 0 43 0xf04 0 44 0xf04 0 45 0xf04 ++ 0 46 0xf04 0 47 0xf04>; + }; + qpend-1 { + qrange = <8704 16>; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2l-clocks.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2l-clocks.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2l-clocks.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2l-clocks.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 lamarr SoC clock nodes + * +- * Copyright (C) 2013-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2013-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + clocks { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2l.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2l.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2l.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2l.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 Lamarr SoC specific device tree + * +- * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2014-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2l-evm.dts b/arch/arm/boot/dts/ti/keystone/keystone-k2l-evm.dts +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2l-evm.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2l-evm.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Keystone 2 Lamarr EVM device tree + * +- * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2014-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + /dts-v1/; + +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/keystone/keystone-k2l-netcp.dtsi b/arch/arm/boot/dts/ti/keystone/keystone-k2l-netcp.dtsi +--- a/arch/arm/boot/dts/ti/keystone/keystone-k2l-netcp.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/keystone/keystone-k2l-netcp.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -2,7 +2,7 @@ + /* + * Device Tree Source for Keystone 2 Lamarr Netcp driver + * +- * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com/ + */ + + qmss: qmss@2a40000 { +@@ -36,9 +36,9 @@ + qpend { + qpend-0 { + qrange = <658 8>; +- interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04 +- 0 43 0xf04 0 44 0xf04 0 45 0xf04 +- 0 46 0xf04 0 47 0xf04>; ++ interrupts = <0 40 0xf04 0 41 0xf04 0 42 0xf04 ++ 0 43 0xf04 0 44 0xf04 0 45 0xf04 ++ 0 46 0xf04 0 47 0xf04>; + }; + qpend-1 { + qrange = <528 16>; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bbb-bone-buses.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bbb-bone-buses.dtsi +--- a/arch/arm/boot/dts/ti/omap/am335x-bbb-bone-buses.dtsi 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bbb-bone-buses.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,69 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 Deepak Khatri ++ * Copyright (C) 2021 Robert Nelson ++ * See Cape Interface Spec page for more info on Bone Buses ++ * https://elinux.org/Beagleboard:BeagleBone_cape_interface_spec ++ * https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html ++ */ ++ ++#include ++#include ++ ++// For dummy refrence when peripheral is not available. ++&{/} { ++ not_available: not_available { ++ // Use ¬_available when required. ++ // This node is responsible to create these entries, ++ // /sys/firmware/devicetree/base/__symbols__/not_available ++ // /sys/firmware/devicetree/base/not_available ++ }; ++}; ++ ++// For compatible bone pinmuxing ++bone_pinmux: &am33xx_pinmux { ++ bborg_comms_can_pins: pinmux_comms_can_pins { ++ pinctrl-single,pins = < ++ 0x184 (PIN_INPUT_PULLUP | MUX_MODE2) /* P9_24: uart1_txd.d_can1_rx */ ++ 0x180 (PIN_OUTPUT_PULLUP | MUX_MODE2) /* P9_26: uart1_rxd.d_can1_tx */ ++ >; ++ }; ++ ++ bborg_comms_rs485_pins: pinmux_comms_rs485_pins { ++ pinctrl-single,pins = < ++ 0x074 (PIN_OUTPUT | MUX_MODE6) /* P9_13: gpmc_wpn.uart4_txd_mux2 */ ++ 0x070 (PIN_INPUT | MUX_MODE6) /* P9_11: gpmc_wait0.uart4_rxd_mux2 */ ++ >; ++ }; ++}; ++ ++// ADC ++bone_adc: &tscadc { ++ ++}; ++ ++// UART ++// https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html#uart ++bone_uart_4: &uart4 { ++ symlink = "bone/uart/4"; ++ status = "disabled"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bborg_comms_rs485_pins>; ++ //rs485-rts-delay = <0 0>; ++ //rts-gpio = <&gpio3 19 1>; /* GPIO_ACTIVE_HIGH>; */ ++ //rs485-rts-active-high; ++ //linux,rs485-enabled-at-boot-time; ++}; ++ ++// CAN ++// https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html#can ++bone_can_1: &dcan1 { ++ symlink = "bone/can/1"; ++ status = "disabled"; ++ pinctrl-names = "default"; ++// pinctrl-0 = < ++// &P9_26_can_pin /* tx */ ++// &P9_24_can_pin /* rx */ ++// >; ++ pinctrl-0 = <&bborg_comms_can_pins>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -12,6 +12,11 @@ + / { + model = "TI AM335x BeagleBone Black"; + compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-boneblack.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; + + &cpu0_opp_table { +@@ -35,7 +40,7 @@ + "P9_18 [spi0_d1]", + "P9_17 [spi0_cs0]", + "[mmc0_cd]", +- "P8_42A [ecappwm0]", ++ "P9_42A [ecappwm0]", + "P8_35 [lcd d12]", + "P8_33 [lcd d13]", + "P8_31 [lcd d14]", +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-boneblack-uboot.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblack-uboot.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-boneblack-uboot.dts 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-boneblack-uboot.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,194 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++/dts-v1/; ++ ++#include "am33xx.dtsi" ++#include "am335x-bone-common.dtsi" ++#include "am335x-bbb-bone-buses.dtsi" ++ ++/ { ++ model = "TI AM335x BeagleBone Black"; ++ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-boneblack-uboot.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; ++ ++ memory@80000000 { ++ device_type = "memory"; ++ reg = <0x80000000 0x20000000>; /* 512 MB */ ++ }; ++}; ++ ++&cpu0_opp_table { ++ /* ++ * All PG 2.0 silicon may not support 1GHz but some of the early ++ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed ++ * to support 1GHz OPP so enable it for PG 2.0 on this board. ++ */ ++ oppnitro-1000000000 { ++ /* OPP Nitro */ ++ opp-supported-hw = <0x06 0x0100>; ++ }; ++}; ++ ++&ldo3_reg { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++}; ++ ++&mmc1 { ++ vmmc-supply = <&vmmcsd_fixed>; ++}; ++ ++&gpio0 { ++ gpio-line-names = ++ "[mdio_data]", ++ "[mdio_clk]", ++ "P9_22 [spi0_sclk]", ++ "P9_21 [spi0_d0]", ++ "P9_18 [spi0_d1]", ++ "P9_17 [spi0_cs0]", ++ "[mmc0_cd]", ++ "P9_42A [ecappwm0]", ++ "P8_35 [lcd d12]", ++ "P8_33 [lcd d13]", ++ "P8_31 [lcd d14]", ++ "P8_32 [lcd d15]", ++ "P9_20 [i2c2_sda]", ++ "P9_19 [i2c2_scl]", ++ "P9_26 [uart1_rxd]", ++ "P9_24 [uart1_txd]", ++ "[rmii1_txd3]", ++ "[rmii1_txd2]", ++ "[usb0_drvvbus]", ++ "[hdmi cec]", ++ "P9_41B", ++ "[rmii1_txd1]", ++ "P8_19 [ehrpwm2a]", ++ "P8_13 [ehrpwm2b]", ++ "NC", ++ "NC", ++ "P8_14", ++ "P8_17", ++ "[rmii1_txd0]", ++ "[rmii1_refclk]", ++ "P9_11 [uart4_rxd]", ++ "P9_13 [uart4_txd]"; ++}; ++ ++&gpio1 { ++ gpio-line-names = ++ "P8_25 [mmc1_dat0]", ++ "[mmc1_dat1]", ++ "P8_5 [mmc1_dat2]", ++ "P8_6 [mmc1_dat3]", ++ "P8_23 [mmc1_dat4]", ++ "P8_22 [mmc1_dat5]", ++ "P8_3 [mmc1_dat6]", ++ "P8_4 [mmc1_dat7]", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "P8_12", ++ "P8_11", ++ "P8_16", ++ "P8_15", ++ "P9_15A", ++ "P9_23", ++ "P9_14 [ehrpwm1a]", ++ "P9_16 [ehrpwm1b]", ++ "[emmc rst]", ++ "[usr0 led]", ++ "[usr1 led]", ++ "[usr2 led]", ++ "[usr3 led]", ++ "[hdmi irq]", ++ "[usb vbus oc]", ++ "[hdmi audio]", ++ "P9_12", ++ "P8_26", ++ "P8_21 [emmc]", ++ "P8_20 [emmc]"; ++}; ++ ++&gpio2 { ++ gpio-line-names = ++ "P9_15B", ++ "P8_18", ++ "P8_7", ++ "P8_8", ++ "P8_10", ++ "P8_9", ++ "P8_45 [hdmi]", ++ "P8_46 [hdmi]", ++ "P8_43 [hdmi]", ++ "P8_44 [hdmi]", ++ "P8_41 [hdmi]", ++ "P8_42 [hdmi]", ++ "P8_39 [hdmi]", ++ "P8_40 [hdmi]", ++ "P8_37 [hdmi]", ++ "P8_38 [hdmi]", ++ "P8_36 [hdmi]", ++ "P8_34 [hdmi]", ++ "[rmii1_rxd3]", ++ "[rmii1_rxd2]", ++ "[rmii1_rxd1]", ++ "[rmii1_rxd0]", ++ "P8_27 [hdmi]", ++ "P8_29 [hdmi]", ++ "P8_28 [hdmi]", ++ "P8_30 [hdmi]", ++ "[mmc0_dat3]", ++ "[mmc0_dat2]", ++ "[mmc0_dat1]", ++ "[mmc0_dat0]", ++ "[mmc0_clk]", ++ "[mmc0_cmd]"; ++}; ++ ++&gpio3 { ++ gpio-line-names = ++ "[mii col]", ++ "[mii crs]", ++ "[mii rx err]", ++ "[mii tx en]", ++ "[mii rx dv]", ++ "[i2c0 sda]", ++ "[i2c0 scl]", ++ "[jtag emu0]", ++ "[jtag emu1]", ++ "[mii tx clk]", ++ "[mii rx clk]", ++ "NC", ++ "NC", ++ "[usb vbus en]", ++ "P9_31 [spi1_sclk]", ++ "P9_29 [spi1_d0]", ++ "P9_30 [spi1_d1]", ++ "P9_28 [spi1_cs0]", ++ "P9_42B [ecappwm0]", ++ "P9_27", ++ "P9_41A", ++ "P9_25", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC"; ++}; ++ ++&baseboard_eeprom { ++ vcc-supply = <&ldo4_reg>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-boneblack-uboot-univ.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblack-uboot-univ.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-boneblack-uboot-univ.dts 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-boneblack-uboot-univ.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,193 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++/dts-v1/; ++ ++#include "am33xx.dtsi" ++#include "am335x-bone-common.dtsi" ++#include "am335x-bone-common-univ.dtsi" ++ ++/ { ++ model = "TI AM335x BeagleBone Black"; ++ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-boneblack-uboot-univ.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; ++ ++ memory@80000000 { ++ device_type = "memory"; ++ reg = <0x80000000 0x20000000>; /* 512 MB */ ++ }; ++}; ++ ++&cpu0_opp_table { ++ /* ++ * All PG 2.0 silicon may not support 1GHz but some of the early ++ * BeagleBone Blacks have PG 2.0 silicon which is guaranteed ++ * to support 1GHz OPP so enable it for PG 2.0 on this board. ++ */ ++ oppnitro-1000000000 { ++ opp-supported-hw = <0x06 0x0100>; ++ }; ++}; ++ ++&ldo3_reg { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++}; ++ ++&mmc1 { ++ vmmc-supply = <&vmmcsd_fixed>; ++}; ++ ++&gpio0 { ++ gpio-line-names = ++ "[mdio_data]", ++ "[mdio_clk]", ++ "P9_22 [spi0_sclk]", ++ "P9_21 [spi0_d0]", ++ "P9_18 [spi0_d1]", ++ "P9_17 [spi0_cs0]", ++ "[mmc0_cd]", ++ "P8_42A [ecappwm0]", ++ "P8_35 [lcd d12]", ++ "P8_33 [lcd d13]", ++ "P8_31 [lcd d14]", ++ "P8_32 [lcd d15]", ++ "P9_20 [i2c2_sda]", ++ "P9_19 [i2c2_scl]", ++ "P9_26 [uart1_rxd]", ++ "P9_24 [uart1_txd]", ++ "[rmii1_txd3]", ++ "[rmii1_txd2]", ++ "[usb0_drvvbus]", ++ "[hdmi cec]", ++ "P9_41B", ++ "[rmii1_txd1]", ++ "P8_19 [ehrpwm2a]", ++ "P8_13 [ehrpwm2b]", ++ "NC", ++ "NC", ++ "P8_14", ++ "P8_17", ++ "[rmii1_txd0]", ++ "[rmii1_refclk]", ++ "P9_11 [uart4_rxd]", ++ "P9_13 [uart4_txd]"; ++}; ++ ++&gpio1 { ++ gpio-line-names = ++ "P8_25 [mmc1_dat0]", ++ "[mmc1_dat1]", ++ "P8_5 [mmc1_dat2]", ++ "P8_6 [mmc1_dat3]", ++ "P8_23 [mmc1_dat4]", ++ "P8_22 [mmc1_dat5]", ++ "P8_3 [mmc1_dat6]", ++ "P8_4 [mmc1_dat7]", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "P8_12", ++ "P8_11", ++ "P8_16", ++ "P8_15", ++ "P9_15A", ++ "P9_23", ++ "P9_14 [ehrpwm1a]", ++ "P9_16 [ehrpwm1b]", ++ "[emmc rst]", ++ "[usr0 led]", ++ "[usr1 led]", ++ "[usr2 led]", ++ "[usr3 led]", ++ "[hdmi irq]", ++ "[usb vbus oc]", ++ "[hdmi audio]", ++ "P9_12", ++ "P8_26", ++ "P8_21 [emmc]", ++ "P8_20 [emmc]"; ++}; ++ ++&gpio2 { ++ gpio-line-names = ++ "P9_15B", ++ "P8_18", ++ "P8_7", ++ "P8_8", ++ "P8_10", ++ "P8_9", ++ "P8_45 [hdmi]", ++ "P8_46 [hdmi]", ++ "P8_43 [hdmi]", ++ "P8_44 [hdmi]", ++ "P8_41 [hdmi]", ++ "P8_42 [hdmi]", ++ "P8_39 [hdmi]", ++ "P8_40 [hdmi]", ++ "P8_37 [hdmi]", ++ "P8_38 [hdmi]", ++ "P8_36 [hdmi]", ++ "P8_34 [hdmi]", ++ "[rmii1_rxd3]", ++ "[rmii1_rxd2]", ++ "[rmii1_rxd1]", ++ "[rmii1_rxd0]", ++ "P8_27 [hdmi]", ++ "P8_29 [hdmi]", ++ "P8_28 [hdmi]", ++ "P8_30 [hdmi]", ++ "[mmc0_dat3]", ++ "[mmc0_dat2]", ++ "[mmc0_dat1]", ++ "[mmc0_dat0]", ++ "[mmc0_clk]", ++ "[mmc0_cmd]"; ++}; ++ ++&gpio3 { ++ gpio-line-names = ++ "[mii col]", ++ "[mii crs]", ++ "[mii rx err]", ++ "[mii tx en]", ++ "[mii rx dv]", ++ "[i2c0 sda]", ++ "[i2c0 scl]", ++ "[jtag emu0]", ++ "[jtag emu1]", ++ "[mii tx clk]", ++ "[mii rx clk]", ++ "NC", ++ "NC", ++ "[usb vbus en]", ++ "P9_31 [spi1_sclk]", ++ "P9_29 [spi1_d0]", ++ "P9_30 [spi1_d1]", ++ "P9_28 [spi1_cs0]", ++ "P9_42B [ecappwm0]", ++ "P9_27", ++ "P9_41A", ++ "P9_25", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC"; ++}; ++ ++&baseboard_eeprom { ++ vcc-supply = <&ldo4_reg>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-boneblack-wireless.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblack-wireless.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-boneblack-wireless.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-boneblack-wireless.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -14,6 +14,11 @@ + model = "TI AM335x BeagleBone Black Wireless"; + compatible = "ti,am335x-bone-black-wireless", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; + ++ chosen { ++ base_dtb = "am335x-boneblack-wireless.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; ++ + wlan_en_reg: fixedregulator@2 { + compatible = "regulator-fixed"; + regulator-name = "wlan-en-regulator"; +@@ -64,6 +69,9 @@ + }; + + &mac_sw { ++ /delete-property/pinctrl-names; ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-1; + status = "disabled"; + }; + +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts b/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-boneblue.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -14,6 +14,8 @@ + + chosen { + stdout-path = &uart0; ++ base_dtb = "am335x-boneblue.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; + }; + + leds { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi +--- a/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bone-common.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -3,6 +3,8 @@ + * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ + */ + ++#include "am335x-bbb-bone-buses.dtsi" ++ + / { + cpus { + cpu@0 { +@@ -26,14 +28,14 @@ + compatible = "gpio-leds"; + + led2 { +- label = "beaglebone:green:heartbeat"; ++ label = "beaglebone:green:usr0"; + gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + led3 { +- label = "beaglebone:green:mmc0"; ++ label = "beaglebone:green:usr1"; + gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; +@@ -63,9 +65,6 @@ + }; + + &am33xx_pinmux { +- pinctrl-names = "default"; +- pinctrl-0 = <&clkout2_pin>; +- + user_leds_s0: user-leds-s0-pins { + pinctrl-single,pins = < + AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ +@@ -96,12 +95,6 @@ + >; + }; + +- clkout2_pin: clkout2-pins { +- pinctrl-single,pins = < +- AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* xdma_event_intr1.clkout2 */ +- >; +- }; +- + cpsw_default: cpsw-default-pins { + pinctrl-single,pins = < + /* Slave 1 */ +@@ -193,6 +186,7 @@ + pinctrl-0 = <&uart0_pins>; + + status = "okay"; ++ symlink = "bone/uart/0"; + }; + + &usb0 { +@@ -211,6 +205,7 @@ + + status = "okay"; + clock-frequency = <400000>; ++ symlink = "bone/i2c/0"; + + tps: tps@24 { + reg = <0x24>; +@@ -235,6 +230,7 @@ + + status = "okay"; + clock-frequency = <100000>; ++ symlink = "bone/i2c/2"; + + cape_eeprom0: cape_eeprom0@54 { + compatible = "atmel,24c256"; +@@ -289,8 +285,8 @@ + * For details, see linux-omap mailing list May 2015 thread + * [PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller + * In particular, messages: +- * http://www.spinics.net/lists/linux-omap/msg118585.html +- * http://www.spinics.net/lists/linux-omap/msg118615.html ++ * https://www.spinics.net/lists/linux-omap/msg118585.html ++ * https://www.spinics.net/lists/linux-omap/msg118615.html + * + * You can override this later with + * &tps { /delete-property/ ti,pmic-shutdown-controller; } +@@ -418,3 +414,12 @@ + &wkup_m3_ipc { + firmware-name = "am335x-bone-scale-data.bin"; + }; ++ ++&tscadc { ++ adc { ++ ti,adc-channels = <0 1 2 3 4 5 6 7>; ++ ti,chan-step-avg = <16 16 16 16 16 16 16 16>; ++ ti,chan-step-opendelay = <0x98 0x98 0x98 0x98 0x98 0x98 0x98 0x98>; ++ ti,chan-step-sampledelay = <0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bone-common-univ.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bone-common-univ.dtsi +--- a/arch/arm/boot/dts/ti/omap/am335x-bone-common-univ.dtsi 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bone-common-univ.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,2289 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++#include ++ ++&am33xx_pinmux { ++ ++/* macro: BONE_PIN( , , */ ++#define BONE_PIN(XX,ZZ,QQ) \ ++ XX##_##ZZ##_pin: pinmux_##XX##_##ZZ##_pin { pinctrl-single,pins = < QQ >; }; ++ ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ /* P8_01 GND */ ++ ++ /* P8_02 GND */ ++ ++ ++ /* P8_03 (ZCZ ball R9) gpmc_ad6 (emmc) */ ++ BONE_PIN(P8_03, default, P8_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_03, gpio, P8_03(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_03, gpio_pu, P8_03(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_03, gpio_pd, P8_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_04 (ZCZ ball T9) gpmc_ad7 (emmc) */ ++ BONE_PIN(P8_04, default, P8_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_04, gpio, P8_04(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_04, gpio_pu, P8_04(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_04, gpio_pd, P8_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_05 (ZCZ ball R8) gpmc_ad2 (emmc) */ ++ BONE_PIN(P8_05, default, P8_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_05, gpio, P8_05(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_05, gpio_pu, P8_05(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_05, gpio_pd, P8_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_06 (ZCZ ball T8) gpmc_ad3 (emmc) */ ++ BONE_PIN(P8_06, default, P8_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_06, gpio, P8_06(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_06, gpio_pu, P8_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_06, gpio_pd, P8_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_07 (ZCZ ball R7) gpmc_advn_ale (gpio2_2) */ ++ BONE_PIN(P8_07, default, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_07, gpio, P8_07(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_07, gpio_pu, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_07, gpio_pd, P8_07(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_07, timer, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_08 (ZCZ ball T7) gpmc_oen_ren (gpio2_3) */ ++ BONE_PIN(P8_08, default, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_08, gpio, P8_08(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_08, gpio_pu, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_08, gpio_pd, P8_08(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_08, timer, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_09 (ZCZ ball T6) gpmc_be0n_cle (gpio2_5) */ ++ BONE_PIN(P8_09, default, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_09, gpio, P8_09(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_09, gpio_pu, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_09, gpio_pd, P8_09(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_09, timer, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_10 (ZCZ ball U6) gpmc_wen (gpio2_4) */ ++ BONE_PIN(P8_10, default, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_10, gpio, P8_10(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_10, gpio_pu, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_10, gpio_pd, P8_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_10, timer, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_11 (ZCZ ball R12) gpmc_ad13 (gpio1_13) */ ++ BONE_PIN(P8_11, default, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, gpio, P8_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, gpio_pu, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, gpio_pd, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, eqep, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P8_11, pruout, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P8_12 (ZCZ ball T12) gpmc_ad12 (gpio1_12) */ ++ BONE_PIN(P8_12, default, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, gpio, P8_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, gpio_pu, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, gpio_pd, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, eqep, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P8_12, pruout, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P8_13 (ZCZ ball T10) gpmc_ad9 (gpio0_23) */ ++ BONE_PIN(P8_13, default, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_13, gpio, P8_13(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_13, gpio_pu, P8_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_13, gpio_pd, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_13, pwm, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_14 (ZCZ ball T11) gpmc_ad10 (gpio0_26) */ ++ BONE_PIN(P8_14, default, P8_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_14, gpio, P8_14(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_14, gpio_pu, P8_14(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_14, gpio_pd, P8_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_14, pwm, P8_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_15 (ZCZ ball U13) gpmc_ad15 (gpio1_15) */ ++ BONE_PIN(P8_15, default, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_15, gpio, P8_15(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_15, gpio_pu, P8_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_15, gpio_pd, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_15, eqep, P8_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P8_15, pru_ecap_pwm, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_15, pruin, P8_15(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_16 (ZCZ ball V13) gpmc_ad14 (gpio1_14) */ ++ BONE_PIN(P8_16, default, P8_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_16, gpio, P8_16(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_16, gpio_pu, P8_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_16, gpio_pd, P8_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_16, eqep, P8_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P8_16, pruin, P8_16(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_17 (ZCZ ball U12) gpmc_ad11 (gpio0_27) */ ++ BONE_PIN(P8_17, default, P8_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_17, gpio, P8_17(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_17, gpio_pu, P8_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_17, gpio_pd, P8_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_17, pwm, P8_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_18 (ZCZ ball V12) gpmc_clk (gpio2_1) */ ++ BONE_PIN(P8_18, default, P8_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_18, gpio, P8_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_18, gpio_pu, P8_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_18, gpio_pd, P8_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_19 (ZCZ ball U10) gpmc_ad8 (gpio0_22) */ ++ BONE_PIN(P8_19, default, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_19, gpio, P8_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_19, gpio_pu, P8_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_19, gpio_pd, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_19, pwm, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_20 (ZCZ ball V9) gpmc_csn2 (emmc) */ ++ BONE_PIN(P8_20, default, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_20, gpio, P8_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_20, gpio_pu, P8_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_20, gpio_pd, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_20, pruout, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_20, pruin, P8_20(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_21 (ZCZ ball U9) gpmc_csn1 (emmc) */ ++ BONE_PIN(P8_21, default, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_21, gpio, P8_21(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_21, gpio_pu, P8_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_21, gpio_pd, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_21, pruout, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_21, pruin, P8_21(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_22 (ZCZ ball V8) gpmc_ad5 (emmc) */ ++ BONE_PIN(P8_22, default, P8_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_22, gpio, P8_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_22, gpio_pu, P8_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_22, gpio_pd, P8_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_23 (ZCZ ball U8) gpmc_ad4 (emmc) */ ++ BONE_PIN(P8_23, default, P8_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_23, gpio, P8_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_23, gpio_pu, P8_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_23, gpio_pd, P8_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_24 (ZCZ ball V7) gpmc_ad1 (emmc) */ ++ BONE_PIN(P8_24, default, P8_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_24, gpio, P8_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_24, gpio_pu, P8_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_24, gpio_pd, P8_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_25 (ZCZ ball U7) gpmc_ad0 (emmc) */ ++ BONE_PIN(P8_25, default, P8_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_25, gpio, P8_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_25, gpio_pu, P8_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_25, gpio_pd, P8_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_26 (ZCZ ball V6) gpmc_csn0 (gpio1_29) */ ++ BONE_PIN(P8_26, default, P8_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_26, gpio, P8_26(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_26, gpio_pu, P8_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_26, gpio_pd, P8_26(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_27 (ZCZ ball U5) lcd_vsync (hdmi) */ ++ BONE_PIN(P8_27, default, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_27, gpio, P8_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_27, gpio_pu, P8_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_27, gpio_pd, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_27, pruout, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_27, pruin, P8_27(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_28 (ZCZ ball V5) lcd_pclk (hdmi) */ ++ BONE_PIN(P8_28, default, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_28, gpio, P8_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_28, gpio_pu, P8_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_28, gpio_pd, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_28, pruout, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_28, pruin, P8_28(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_29 (ZCZ ball R5) lcd_hsync (hdmi) */ ++ BONE_PIN(P8_29, default, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_29, gpio, P8_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_29, gpio_pu, P8_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_29, gpio_pd, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_29, pruout, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_29, pruin, P8_29(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_30 (ZCZ ball R6) lcd_ac_bias_en (hdmi) */ ++ BONE_PIN(P8_30, default, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_30, gpio, P8_30(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_30, gpio_pu, P8_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_30, gpio_pd, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_30, pruout, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_30, pruin, P8_30(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_31 (ZCZ ball V4) lcd_data14 (hdmi) */ ++ BONE_PIN(P8_31, default, P8_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_31, gpio, P8_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_31, gpio_pu, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_31, gpio_pd, P8_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_31, eqep, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P8_31, uart, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_32 (ZCZ ball T5) lcd_data15 (hdmi) */ ++ BONE_PIN(P8_32, default, P8_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_32, gpio, P8_32(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_32, gpio_pu, P8_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_32, gpio_pd, P8_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_32, eqep, P8_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_33 (ZCZ ball V3) lcd_data13 (hdmi) */ ++ BONE_PIN(P8_33, default, P8_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_33, gpio, P8_33(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_33, gpio_pu, P8_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_33, gpio_pd, P8_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_33, eqep, P8_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_34 (ZCZ ball U4) lcd_data11 (hdmi) */ ++ BONE_PIN(P8_34, default, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_34, gpio, P8_34(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_34, gpio_pu, P8_34(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_34, gpio_pd, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_34, pwm, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_35 (ZCZ ball V2) lcd_data12 (hdmi) */ ++ BONE_PIN(P8_35, default, P8_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_35, gpio, P8_35(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_35, gpio_pu, P8_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_35, gpio_pd, P8_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_35, eqep, P8_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_36 (ZCZ ball U3) lcd_data10 (hdmi) */ ++ BONE_PIN(P8_36, default, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_36, gpio, P8_36(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_36, gpio_pu, P8_36(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_36, gpio_pd, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_36, pwm, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_37 (ZCZ ball U1) lcd_data8 (hdmi) */ ++ BONE_PIN(P8_37, default, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_37, gpio, P8_37(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_37, gpio_pu, P8_37(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_37, gpio_pd, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_37, pwm, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P8_37, uart, P8_37(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_38 (ZCZ ball U2) lcd_data9 (hdmi) */ ++ BONE_PIN(P8_38, default, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_38, gpio, P8_38(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_38, gpio_pu, P8_38(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_38, gpio_pd, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_38, pwm, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P8_38, uart, P8_38(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_39 (ZCZ ball T3) lcd_data6 (hdmi) */ ++ BONE_PIN(P8_39, default, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_39, gpio, P8_39(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_39, gpio_pu, P8_39(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_39, gpio_pd, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_39, eqep, P8_39(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_39, pruout, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_39, pruin, P8_39(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_40 (ZCZ ball T4) lcd_data7 (hdmi) */ ++ BONE_PIN(P8_40, default, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_40, gpio, P8_40(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_40, gpio_pu, P8_40(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_40, gpio_pd, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_40, eqep, P8_40(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_40, pruout, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_40, pruin, P8_40(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_41 (ZCZ ball T1) lcd_data4 (hdmi) */ ++ BONE_PIN(P8_41, default, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_41, gpio, P8_41(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_41, gpio_pu, P8_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_41, gpio_pd, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_41, eqep, P8_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_41, pruout, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_41, pruin, P8_41(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_42 (ZCZ ball T2) lcd_data5 (hdmi) */ ++ BONE_PIN(P8_42, default, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_42, gpio, P8_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_42, gpio_pu, P8_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_42, gpio_pd, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_42, eqep, P8_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_42, pruout, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_42, pruin, P8_42(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_43 (ZCZ ball R3) lcd_data2 (hdmi) */ ++ BONE_PIN(P8_43, default, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_43, gpio, P8_43(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_43, gpio_pu, P8_43(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_43, gpio_pd, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_43, pwm, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_43, pruout, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_43, pruin, P8_43(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_44 (ZCZ ball R4) lcd_data3 (hdmi) */ ++ BONE_PIN(P8_44, default, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_44, gpio, P8_44(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_44, gpio_pu, P8_44(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_44, gpio_pd, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_44, pwm, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_44, pruout, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_44, pruin, P8_44(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_45 (ZCZ ball R1) lcd_data0 (hdmi) */ ++ BONE_PIN(P8_45, default, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_45, gpio, P8_45(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_45, gpio_pu, P8_45(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_45, gpio_pd, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_45, pwm, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_45, pruout, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_45, pruin, P8_45(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_46 (ZCZ ball R2) lcd_data1 (hdmi) */ ++ BONE_PIN(P8_46, default, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_46, gpio, P8_46(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_46, gpio_pu, P8_46(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_46, gpio_pd, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_46, pwm, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_46, pruout, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_46, pruin, P8_46(PIN_INPUT | MUX_MODE6)) ++ ++ /************************/ ++ /* P9 Header */ ++ /************************/ ++ ++ /* P9_01 GND */ ++ ++ /* P9_02 GND */ ++ ++ /* P9_03 3V3 */ ++ ++ /* P9_04 3V3 */ ++ ++ /* P9_05 VDD_5V */ ++ ++ /* P9_06 VDD_5V */ ++ ++ /* P9_07 SYS_5V */ ++ ++ /* P9_08 SYS_5V */ ++ ++ /* P9_09 PWR_BUT */ ++ ++ /* P9_10 RSTn */ ++ ++ /* P9_11 (ZCZ ball T17) gpmc_wait0 (gpio0_30) */ ++ BONE_PIN(P9_11, default, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_11, gpio, P9_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_11, gpio_pu, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_11, gpio_pd, P9_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_11, uart, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_12 (ZCZ ball U18) gpmc_be1n (gpio1_28) */ ++ BONE_PIN(P9_12, default, P9_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_12, gpio, P9_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_12, gpio_pu, P9_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_12, gpio_pd, P9_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P9_13 (ZCZ ball U17) gpmc_wpn (gpio0_31) */ ++ BONE_PIN(P9_13, default, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_13, gpio, P9_13(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_13, gpio_pu, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_13, gpio_pd, P9_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_13, uart, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_14 (ZCZ ball U14) gpmc_a2 (gpio1_18) */ ++ BONE_PIN(P9_14, default, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, gpio, P9_14(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, gpio_pu, P9_14(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, gpio_pd, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, pwm, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_15 (ZCZ ball R13) gpmc_a0 (gpio1_16) */ ++ BONE_PIN(P9_15, default, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_15, gpio, P9_15(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_15, gpio_pu, P9_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_15, gpio_pd, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_15, pwm, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_16 (ZCZ ball T14) gpmc_a3 (gpio1_19) */ ++ BONE_PIN(P9_16, default, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_16, gpio, P9_16(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_16, gpio_pu, P9_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_16, gpio_pd, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_16, pwm, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_17 (ZCZ ball A16) spi0_cs0 (gpio0_5) */ ++ BONE_PIN(P9_17, default, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_17, gpio, P9_17(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_17, gpio_pu, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_17, gpio_pd, P9_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_17, spi_cs, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_17, i2c, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_17, pwm, P9_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_17, pru_uart, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P9_18 (ZCZ ball B16) spi0_d1 (gpio0_4) */ ++ BONE_PIN(P9_18, default, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_18, gpio, P9_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_18, gpio_pu, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_18, gpio_pd, P9_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_18, spi, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_18, i2c, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_18, pwm, P9_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_18, pru_uart, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P9_19 (ZCZ ball D17) uart1_rtsn (i2c2_scl) */ ++ BONE_PIN(P9_19, default, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_19, gpio, P9_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_19, gpio_pu, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_19, gpio_pd, P9_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_19, timer, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_19, can, P9_19(PIN_INPUT_PULLUP | MUX_MODE2)) ++ BONE_PIN(P9_19, i2c, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_19, spi_cs, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P9_19, pru_uart, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5)) ++ ++ /* P9_20 (ZCZ ball D18) uart1_ctsn (i2c2_sda) */ ++ BONE_PIN(P9_20, default, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_20, gpio, P9_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_20, gpio_pu, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_20, gpio_pd, P9_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_20, timer, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_20, can, P9_20(PIN_OUTPUT_PULLUP | MUX_MODE2)) ++ BONE_PIN(P9_20, i2c, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_20, spi_cs, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P9_20, pru_uart, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5)) ++ ++ /* P9_21 (ZCZ ball B17) spi0_d0 (gpio0_3) */ ++ BONE_PIN(P9_21, default, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_21, gpio, P9_21(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_21, gpio_pu, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_21, gpio_pd, P9_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_21, spi, P9_21(PIN_INPUT_PULLUP | MUX_MODE0)) ++ BONE_PIN(P9_21, uart, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_21, i2c, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_21, pwm, P9_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_21, pru_uart, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P9_22 (ZCZ ball A17) spi0_sclk (gpio0_2) */ ++ BONE_PIN(P9_22, default, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_22, gpio, P9_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_22, gpio_pu, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_22, gpio_pd, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_22, spi_sclk, P9_22(PIN_INPUT_PULLUP | MUX_MODE0)) ++ BONE_PIN(P9_22, uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_22, i2c, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_22, pwm, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_22, pru_uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P9_23 (ZCZ ball V14) gpmc_a1 (gpio1_17) */ ++ BONE_PIN(P9_23, default, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, gpio, P9_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, gpio_pu, P9_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, gpio_pd, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, pwm, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_24 (ZCZ ball D15) uart1_txd (gpio0_15) */ ++ BONE_PIN(P9_24, default, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_24, gpio, P9_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_24, gpio_pu, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_24, gpio_pd, P9_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_24, uart, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_24, can, P9_24(PIN_INPUT_PULLUP | MUX_MODE2)) ++ BONE_PIN(P9_24, i2c, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_24, pru_uart, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_24, pruin, P9_24(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_25 (ZCZ ball A14) mcasp0_ahclkx (audio) */ ++ BONE_PIN(P9_25, default, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_25, gpio, P9_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_25, gpio_pu, P9_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_25, gpio_pd, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_25, eqep, P9_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_25, pruout, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_25, pruin, P9_25(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_26 (ZCZ ball D16) uart1_rxd (gpio0_14) */ ++ BONE_PIN(P9_26, default, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_26, gpio, P9_26(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_26, gpio_pu, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_26, gpio_pd, P9_26(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_26, uart, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_26, can, P9_26(PIN_OUTPUT_PULLUP | MUX_MODE2)) ++ BONE_PIN(P9_26, i2c, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_26, pru_uart, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_26, pruin, P9_26(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_27 (ZCZ ball C13) mcasp0_fsr (gpio3_19) */ ++ BONE_PIN(P9_27, default, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_27, gpio, P9_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_27, gpio_pu, P9_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_27, gpio_pd, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_27, eqep, P9_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_27, pruout, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_27, pruin, P9_27(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_28 (ZCZ ball C12) mcasp0_ahclkr (audio) */ ++ BONE_PIN(P9_28, default, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_28, gpio, P9_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_28, gpio_pu, P9_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_28, gpio_pd, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_28, pwm, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_28, spi_cs, P9_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_28, pwm2, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P9_28, pruout, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_28, pruin, P9_28(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_29 (ZCZ ball B13) mcasp0_fsx (audio) */ ++ BONE_PIN(P9_29, default, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_29, gpio, P9_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_29, gpio_pu, P9_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_29, gpio_pd, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_29, pwm, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_29, spi, P9_29(PIN_INPUT_PULLUP | MUX_MODE3)) ++ BONE_PIN(P9_29, pruout, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_29, pruin, P9_29(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_30 (ZCZ ball D12) mcasp0_axr0 (gpio3_16) */ ++ BONE_PIN(P9_30, default, P9_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_30, gpio, P9_30(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_30, gpio_pu, P9_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_30, gpio_pd, P9_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_30, pwm, P9_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_30, spi, P9_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_30, pruout, P9_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_30, pruin, P9_30(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_31 (ZCZ ball A13) mcasp0_aclkx (audio) */ ++ BONE_PIN(P9_31, default, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_31, gpio, P9_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_31, gpio_pu, P9_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_31, gpio_pd, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_31, pwm, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_31, spi_sclk, P9_31(PIN_INPUT_PULLUP | MUX_MODE3)) ++ BONE_PIN(P9_31, pruout, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_31, pruin, P9_31(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_32 VADC */ ++ ++ /* P9_33 (ZCZ ball C8) AIN4 */ ++ ++ /* P9_34 AGND */ ++ ++ /* P9_35 (ZCZ ball A8) AIN6 */ ++ ++ /* P9_36 (ZCZ ball B8) AIN5 */ ++ ++ /* P9_37 (ZCZ ball B7) AIN2 */ ++ ++ /* P9_38 (ZCZ ball A7) AIN3 */ ++ ++ /* P9_39 (ZCZ ball B6) AIN0 */ ++ ++ /* P9_40 (ZCZ ball C7) AIN1 */ ++ ++ /* P9_41 (ZCZ ball D14) xdma_event_intr1 (gpio0_20) */ ++ BONE_PIN(P9_41, default, P9_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_41, gpio, P9_41(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_41, gpio_pu, P9_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_41, gpio_pd, P9_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_41, timer, P9_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P9_41, pruin, P9_41(PIN_INPUT | MUX_MODE5)) ++ ++ /* P9_41.1 */ ++ /* P9_91 (ZCZ ball D13) mcasp0_axr1 (gpio3_20) */ ++ BONE_PIN(P9_91, default, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_91, gpio, P9_91(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_91, gpio_pu, P9_91(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_91, gpio_pd, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_91, eqep, P9_91(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_91, pruout, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_91, pruin, P9_91(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_42 (ZCZ ball C18) eCAP0_in_PWM0_out (gpio0_7) */ ++ BONE_PIN(P9_42, default, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, gpio, P9_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, gpio_pu, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, gpio_pd, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, pwm, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_42, uart, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_42, spi_cs, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_42, pru_ecap_pwm, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_42, spi_sclk, P9_42(PIN_INPUT_PULLUP | MUX_MODE4)) ++ ++ /* P9_42.1 */ ++ /* P9_92 (ZCZ ball B12) mcasp0_aclkr (gpio3_18) */ ++ BONE_PIN(P9_92, default, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, gpio, P9_92(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, gpio_pu, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, gpio_pd, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, eqep, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_92, pruout, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_92, pruin, P9_92(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_43 GND */ ++ ++ /* P9_44 GND */ ++ ++ /* P9_45 GND */ ++ ++ /* P9_46 GND */ ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ clock-frequency = <100000>; ++ symlink = "bone/i2c/1"; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ clock-frequency = <100000>; ++ symlink = "bone/i2c/2"; ++}; ++ ++&uart1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/1"; ++}; ++ ++&uart2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/2"; ++}; ++ ++&uart3 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/3"; ++}; ++ ++&uart4 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/4"; ++}; ++ ++&uart5 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/5"; ++}; ++ ++&dcan0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/can/0"; ++}; ++ ++&dcan1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/can/1"; ++}; ++ ++&eqep0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/eqep/0"; ++}; ++ ++&eqep1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/eqep/1"; ++}; ++ ++&eqep2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/eqep/2"; ++}; ++ ++&epwmss0 { ++ status = "okay"; ++}; ++ ++&epwmss1 { ++ status = "okay"; ++}; ++ ++&epwmss2 { ++ status = "okay"; ++}; ++ ++&ehrpwm0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ehrpwm1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ehrpwm2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ecap0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ecap1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ecap2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&spi0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/0.0"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/0.1"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++}; ++ ++&spi1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/1.0"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/1.1"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++}; ++ ++/**********************************************************************/ ++/* Pin Multiplex Helpers */ ++/* */ ++/* These provide userspace runtime pin configuration for the */ ++/* BeagleBone cape expansion headers */ ++/**********************************************************************/ ++ ++&ocp { ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ /* P8_01 GND */ ++ ++ /* P8_02 GND */ ++ ++ ++ /* P8_03 (ZCZ ball R9) emmc */ ++ P8_03_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_03_default_pin>; ++ pinctrl-1 = <&P8_03_gpio_pin>; ++ pinctrl-2 = <&P8_03_gpio_pu_pin>; ++ pinctrl-3 = <&P8_03_gpio_pd_pin>; ++ }; ++ ++ /* P8_04 (ZCZ ball T9) emmc */ ++ P8_04_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_04_default_pin>; ++ pinctrl-1 = <&P8_04_gpio_pin>; ++ pinctrl-2 = <&P8_04_gpio_pu_pin>; ++ pinctrl-3 = <&P8_04_gpio_pd_pin>; ++ }; ++ ++ /* P8_05 (ZCZ ball R8) emmc */ ++ P8_05_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_05_default_pin>; ++ pinctrl-1 = <&P8_05_gpio_pin>; ++ pinctrl-2 = <&P8_05_gpio_pu_pin>; ++ pinctrl-3 = <&P8_05_gpio_pd_pin>; ++ }; ++ ++ /* P8_06 (ZCZ ball T8) emmc */ ++ P8_06_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_06_default_pin>; ++ pinctrl-1 = <&P8_06_gpio_pin>; ++ pinctrl-2 = <&P8_06_gpio_pu_pin>; ++ pinctrl-3 = <&P8_06_gpio_pd_pin>; ++ }; ++ ++ /* P8_07 (ZCZ ball R7) */ ++ P8_07_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_07_default_pin>; ++ pinctrl-1 = <&P8_07_gpio_pin>; ++ pinctrl-2 = <&P8_07_gpio_pu_pin>; ++ pinctrl-3 = <&P8_07_gpio_pd_pin>; ++ pinctrl-4 = <&P8_07_timer_pin>; ++ }; ++ ++ /* P8_08 (ZCZ ball T7) */ ++ P8_08_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_08_default_pin>; ++ pinctrl-1 = <&P8_08_gpio_pin>; ++ pinctrl-2 = <&P8_08_gpio_pu_pin>; ++ pinctrl-3 = <&P8_08_gpio_pd_pin>; ++ pinctrl-4 = <&P8_08_timer_pin>; ++ }; ++ ++ /* P8_09 (ZCZ ball T6) */ ++ P8_09_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_09_default_pin>; ++ pinctrl-1 = <&P8_09_gpio_pin>; ++ pinctrl-2 = <&P8_09_gpio_pu_pin>; ++ pinctrl-3 = <&P8_09_gpio_pd_pin>; ++ pinctrl-4 = <&P8_09_timer_pin>; ++ }; ++ ++ /* P8_10 (ZCZ ball U6) */ ++ P8_10_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_10_default_pin>; ++ pinctrl-1 = <&P8_10_gpio_pin>; ++ pinctrl-2 = <&P8_10_gpio_pu_pin>; ++ pinctrl-3 = <&P8_10_gpio_pd_pin>; ++ pinctrl-4 = <&P8_10_timer_pin>; ++ }; ++ ++ /* P8_11 (ZCZ ball R12) */ ++ P8_11_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout"; ++ pinctrl-0 = <&P8_11_default_pin>; ++ pinctrl-1 = <&P8_11_gpio_pin>; ++ pinctrl-2 = <&P8_11_gpio_pu_pin>; ++ pinctrl-3 = <&P8_11_gpio_pd_pin>; ++ pinctrl-4 = <&P8_11_eqep_pin>; ++ pinctrl-5 = <&P8_11_pruout_pin>; ++ }; ++ ++ /* P8_12 (ZCZ ball T12) */ ++ P8_12_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout"; ++ pinctrl-0 = <&P8_12_default_pin>; ++ pinctrl-1 = <&P8_12_gpio_pin>; ++ pinctrl-2 = <&P8_12_gpio_pu_pin>; ++ pinctrl-3 = <&P8_12_gpio_pd_pin>; ++ pinctrl-4 = <&P8_12_eqep_pin>; ++ pinctrl-5 = <&P8_12_pruout_pin>; ++ }; ++ ++ /* P8_13 (ZCZ ball T10) */ ++ P8_13_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_13_default_pin>; ++ pinctrl-1 = <&P8_13_gpio_pin>; ++ pinctrl-2 = <&P8_13_gpio_pu_pin>; ++ pinctrl-3 = <&P8_13_gpio_pd_pin>; ++ pinctrl-4 = <&P8_13_pwm_pin>; ++ }; ++ ++ /* P8_14 (ZCZ ball T11) */ ++ P8_14_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_14_default_pin>; ++ pinctrl-1 = <&P8_14_gpio_pin>; ++ pinctrl-2 = <&P8_14_gpio_pu_pin>; ++ pinctrl-3 = <&P8_14_gpio_pd_pin>; ++ pinctrl-4 = <&P8_14_pwm_pin>; ++ }; ++ ++ /* P8_15 (ZCZ ball U13) */ ++ P8_15_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pru_ecap_pwm", "pruin"; ++ pinctrl-0 = <&P8_15_default_pin>; ++ pinctrl-1 = <&P8_15_gpio_pin>; ++ pinctrl-2 = <&P8_15_gpio_pu_pin>; ++ pinctrl-3 = <&P8_15_gpio_pd_pin>; ++ pinctrl-4 = <&P8_15_eqep_pin>; ++ pinctrl-5 = <&P8_15_pru_ecap_pwm_pin>; ++ pinctrl-6 = <&P8_15_pruin_pin>; ++ }; ++ ++ /* P8_16 (ZCZ ball V13) */ ++ P8_16_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruin"; ++ pinctrl-0 = <&P8_16_default_pin>; ++ pinctrl-1 = <&P8_16_gpio_pin>; ++ pinctrl-2 = <&P8_16_gpio_pu_pin>; ++ pinctrl-3 = <&P8_16_gpio_pd_pin>; ++ pinctrl-4 = <&P8_16_eqep_pin>; ++ pinctrl-5 = <&P8_16_pruin_pin>; ++ }; ++ ++ /* P8_17 (ZCZ ball U12) */ ++ P8_17_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_17_default_pin>; ++ pinctrl-1 = <&P8_17_gpio_pin>; ++ pinctrl-2 = <&P8_17_gpio_pu_pin>; ++ pinctrl-3 = <&P8_17_gpio_pd_pin>; ++ pinctrl-4 = <&P8_17_pwm_pin>; ++ }; ++ ++ /* P8_18 (ZCZ ball V12) */ ++ P8_18_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_18_default_pin>; ++ pinctrl-1 = <&P8_18_gpio_pin>; ++ pinctrl-2 = <&P8_18_gpio_pu_pin>; ++ pinctrl-3 = <&P8_18_gpio_pd_pin>; ++ }; ++ ++ /* P8_19 (ZCZ ball U10) */ ++ P8_19_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_19_default_pin>; ++ pinctrl-1 = <&P8_19_gpio_pin>; ++ pinctrl-2 = <&P8_19_gpio_pu_pin>; ++ pinctrl-3 = <&P8_19_gpio_pd_pin>; ++ pinctrl-4 = <&P8_19_pwm_pin>; ++ }; ++ ++ /* P8_20 (ZCZ ball V9) emmc */ ++ P8_20_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_20_default_pin>; ++ pinctrl-1 = <&P8_20_gpio_pin>; ++ pinctrl-2 = <&P8_20_gpio_pu_pin>; ++ pinctrl-3 = <&P8_20_gpio_pd_pin>; ++ pinctrl-4 = <&P8_20_pruout_pin>; ++ pinctrl-5 = <&P8_20_pruin_pin>; ++ }; ++ ++ /* P8_21 (ZCZ ball U9) emmc */ ++ P8_21_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_21_default_pin>; ++ pinctrl-1 = <&P8_21_gpio_pin>; ++ pinctrl-2 = <&P8_21_gpio_pu_pin>; ++ pinctrl-3 = <&P8_21_gpio_pd_pin>; ++ pinctrl-4 = <&P8_21_pruout_pin>; ++ pinctrl-5 = <&P8_21_pruin_pin>; ++ }; ++ ++ /* P8_22 (ZCZ ball V8) emmc */ ++ P8_22_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_22_default_pin>; ++ pinctrl-1 = <&P8_22_gpio_pin>; ++ pinctrl-2 = <&P8_22_gpio_pu_pin>; ++ pinctrl-3 = <&P8_22_gpio_pd_pin>; ++ }; ++ ++ /* P8_23 (ZCZ ball U8) emmc */ ++ P8_23_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_23_default_pin>; ++ pinctrl-1 = <&P8_23_gpio_pin>; ++ pinctrl-2 = <&P8_23_gpio_pu_pin>; ++ pinctrl-3 = <&P8_23_gpio_pd_pin>; ++ }; ++ ++ /* P8_24 (ZCZ ball V7) emmc */ ++ P8_24_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_24_default_pin>; ++ pinctrl-1 = <&P8_24_gpio_pin>; ++ pinctrl-2 = <&P8_24_gpio_pu_pin>; ++ pinctrl-3 = <&P8_24_gpio_pd_pin>; ++ }; ++ ++ /* P8_25 (ZCZ ball U7) emmc */ ++ P8_25_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_25_default_pin>; ++ pinctrl-1 = <&P8_25_gpio_pin>; ++ pinctrl-2 = <&P8_25_gpio_pu_pin>; ++ pinctrl-3 = <&P8_25_gpio_pd_pin>; ++ }; ++ ++ /* P8_26 (ZCZ ball V6) */ ++ P8_26_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_26_default_pin>; ++ pinctrl-1 = <&P8_26_gpio_pin>; ++ pinctrl-2 = <&P8_26_gpio_pu_pin>; ++ pinctrl-3 = <&P8_26_gpio_pd_pin>; ++ }; ++ ++ /* P8_27 (ZCZ ball U5) hdmi */ ++ P8_27_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_27_default_pin>; ++ pinctrl-1 = <&P8_27_gpio_pin>; ++ pinctrl-2 = <&P8_27_gpio_pu_pin>; ++ pinctrl-3 = <&P8_27_gpio_pd_pin>; ++ pinctrl-4 = <&P8_27_pruout_pin>; ++ pinctrl-5 = <&P8_27_pruin_pin>; ++ }; ++ ++ /* P8_28 (ZCZ ball V5) hdmi */ ++ P8_28_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_28_default_pin>; ++ pinctrl-1 = <&P8_28_gpio_pin>; ++ pinctrl-2 = <&P8_28_gpio_pu_pin>; ++ pinctrl-3 = <&P8_28_gpio_pd_pin>; ++ pinctrl-4 = <&P8_28_pruout_pin>; ++ pinctrl-5 = <&P8_28_pruin_pin>; ++ }; ++ ++ /* P8_29 (ZCZ ball R5) hdmi */ ++ P8_29_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_29_default_pin>; ++ pinctrl-1 = <&P8_29_gpio_pin>; ++ pinctrl-2 = <&P8_29_gpio_pu_pin>; ++ pinctrl-3 = <&P8_29_gpio_pd_pin>; ++ pinctrl-4 = <&P8_29_pruout_pin>; ++ pinctrl-5 = <&P8_29_pruin_pin>; ++ }; ++ ++ /* P8_30 (ZCZ ball R6) hdmi */ ++ P8_30_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_30_default_pin>; ++ pinctrl-1 = <&P8_30_gpio_pin>; ++ pinctrl-2 = <&P8_30_gpio_pu_pin>; ++ pinctrl-3 = <&P8_30_gpio_pd_pin>; ++ pinctrl-4 = <&P8_30_pruout_pin>; ++ pinctrl-5 = <&P8_30_pruin_pin>; ++ }; ++ ++ /* P8_31 (ZCZ ball V4) hdmi */ ++ P8_31_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "eqep"; ++ pinctrl-0 = <&P8_31_default_pin>; ++ pinctrl-1 = <&P8_31_gpio_pin>; ++ pinctrl-2 = <&P8_31_gpio_pu_pin>; ++ pinctrl-3 = <&P8_31_gpio_pd_pin>; ++ pinctrl-4 = <&P8_31_uart_pin>; ++ pinctrl-5 = <&P8_31_eqep_pin>; ++ }; ++ ++ /* P8_32 (ZCZ ball T5) hdmi */ ++ P8_32_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep"; ++ pinctrl-0 = <&P8_32_default_pin>; ++ pinctrl-1 = <&P8_32_gpio_pin>; ++ pinctrl-2 = <&P8_32_gpio_pu_pin>; ++ pinctrl-3 = <&P8_32_gpio_pd_pin>; ++ pinctrl-4 = <&P8_32_eqep_pin>; ++ }; ++ ++ /* P8_33 (ZCZ ball V3) hdmi */ ++ P8_33_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep"; ++ pinctrl-0 = <&P8_33_default_pin>; ++ pinctrl-1 = <&P8_33_gpio_pin>; ++ pinctrl-2 = <&P8_33_gpio_pu_pin>; ++ pinctrl-3 = <&P8_33_gpio_pd_pin>; ++ pinctrl-4 = <&P8_33_eqep_pin>; ++ }; ++ ++ /* P8_34 (ZCZ ball U4) hdmi */ ++ P8_34_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_34_default_pin>; ++ pinctrl-1 = <&P8_34_gpio_pin>; ++ pinctrl-2 = <&P8_34_gpio_pu_pin>; ++ pinctrl-3 = <&P8_34_gpio_pd_pin>; ++ pinctrl-4 = <&P8_34_pwm_pin>; ++ }; ++ ++ /* P8_35 (ZCZ ball V2) hdmi */ ++ P8_35_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep"; ++ pinctrl-0 = <&P8_35_default_pin>; ++ pinctrl-1 = <&P8_35_gpio_pin>; ++ pinctrl-2 = <&P8_35_gpio_pu_pin>; ++ pinctrl-3 = <&P8_35_gpio_pd_pin>; ++ pinctrl-4 = <&P8_35_eqep_pin>; ++ }; ++ ++ /* P8_36 (ZCZ ball U3) hdmi */ ++ P8_36_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_36_default_pin>; ++ pinctrl-1 = <&P8_36_gpio_pin>; ++ pinctrl-2 = <&P8_36_gpio_pu_pin>; ++ pinctrl-3 = <&P8_36_gpio_pd_pin>; ++ pinctrl-4 = <&P8_36_pwm_pin>; ++ }; ++ ++ /* P8_37 (ZCZ ball U1) hdmi */ ++ P8_37_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "pwm"; ++ pinctrl-0 = <&P8_37_default_pin>; ++ pinctrl-1 = <&P8_37_gpio_pin>; ++ pinctrl-2 = <&P8_37_gpio_pu_pin>; ++ pinctrl-3 = <&P8_37_gpio_pd_pin>; ++ pinctrl-4 = <&P8_37_uart_pin>; ++ pinctrl-5 = <&P8_37_pwm_pin>; ++ }; ++ ++ /* P8_38 (ZCZ ball U2) hdmi */ ++ P8_38_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "pwm"; ++ pinctrl-0 = <&P8_38_default_pin>; ++ pinctrl-1 = <&P8_38_gpio_pin>; ++ pinctrl-2 = <&P8_38_gpio_pu_pin>; ++ pinctrl-3 = <&P8_38_gpio_pd_pin>; ++ pinctrl-4 = <&P8_38_uart_pin>; ++ pinctrl-5 = <&P8_38_pwm_pin>; ++ }; ++ ++ /* P8_39 (ZCZ ball T3) hdmi */ ++ P8_39_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P8_39_default_pin>; ++ pinctrl-1 = <&P8_39_gpio_pin>; ++ pinctrl-2 = <&P8_39_gpio_pu_pin>; ++ pinctrl-3 = <&P8_39_gpio_pd_pin>; ++ pinctrl-4 = <&P8_39_eqep_pin>; ++ pinctrl-5 = <&P8_39_pruout_pin>; ++ pinctrl-6 = <&P8_39_pruin_pin>; ++ }; ++ ++ /* P8_40 (ZCZ ball T4) hdmi */ ++ P8_40_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P8_40_default_pin>; ++ pinctrl-1 = <&P8_40_gpio_pin>; ++ pinctrl-2 = <&P8_40_gpio_pu_pin>; ++ pinctrl-3 = <&P8_40_gpio_pd_pin>; ++ pinctrl-4 = <&P8_40_eqep_pin>; ++ pinctrl-5 = <&P8_40_pruout_pin>; ++ pinctrl-6 = <&P8_40_pruin_pin>; ++ }; ++ ++ /* P8_41 (ZCZ ball T1) hdmi */ ++ P8_41_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P8_41_default_pin>; ++ pinctrl-1 = <&P8_41_gpio_pin>; ++ pinctrl-2 = <&P8_41_gpio_pu_pin>; ++ pinctrl-3 = <&P8_41_gpio_pd_pin>; ++ pinctrl-4 = <&P8_41_eqep_pin>; ++ pinctrl-5 = <&P8_41_pruout_pin>; ++ pinctrl-6 = <&P8_41_pruin_pin>; ++ }; ++ ++ /* P8_42 (ZCZ ball T2) hdmi */ ++ P8_42_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P8_42_default_pin>; ++ pinctrl-1 = <&P8_42_gpio_pin>; ++ pinctrl-2 = <&P8_42_gpio_pu_pin>; ++ pinctrl-3 = <&P8_42_gpio_pd_pin>; ++ pinctrl-4 = <&P8_42_eqep_pin>; ++ pinctrl-5 = <&P8_42_pruout_pin>; ++ pinctrl-6 = <&P8_42_pruin_pin>; ++ }; ++ ++ /* P8_43 (ZCZ ball R3) hdmi */ ++ P8_43_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P8_43_default_pin>; ++ pinctrl-1 = <&P8_43_gpio_pin>; ++ pinctrl-2 = <&P8_43_gpio_pu_pin>; ++ pinctrl-3 = <&P8_43_gpio_pd_pin>; ++ pinctrl-4 = <&P8_43_pwm_pin>; ++ pinctrl-5 = <&P8_43_pruout_pin>; ++ pinctrl-6 = <&P8_43_pruin_pin>; ++ }; ++ ++ /* P8_44 (ZCZ ball R4) hdmi */ ++ P8_44_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P8_44_default_pin>; ++ pinctrl-1 = <&P8_44_gpio_pin>; ++ pinctrl-2 = <&P8_44_gpio_pu_pin>; ++ pinctrl-3 = <&P8_44_gpio_pd_pin>; ++ pinctrl-4 = <&P8_44_pwm_pin>; ++ pinctrl-5 = <&P8_44_pruout_pin>; ++ pinctrl-6 = <&P8_44_pruin_pin>; ++ }; ++ ++ /* P8_45 (ZCZ ball R1) hdmi */ ++ P8_45_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P8_45_default_pin>; ++ pinctrl-1 = <&P8_45_gpio_pin>; ++ pinctrl-2 = <&P8_45_gpio_pu_pin>; ++ pinctrl-3 = <&P8_45_gpio_pd_pin>; ++ pinctrl-4 = <&P8_45_pwm_pin>; ++ pinctrl-5 = <&P8_45_pruout_pin>; ++ pinctrl-6 = <&P8_45_pruin_pin>; ++ }; ++ ++ /* P8_46 (ZCZ ball R2) hdmi */ ++ P8_46_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P8_46_default_pin>; ++ pinctrl-1 = <&P8_46_gpio_pin>; ++ pinctrl-2 = <&P8_46_gpio_pu_pin>; ++ pinctrl-3 = <&P8_46_gpio_pd_pin>; ++ pinctrl-4 = <&P8_46_pwm_pin>; ++ pinctrl-5 = <&P8_46_pruout_pin>; ++ pinctrl-6 = <&P8_46_pruin_pin>; ++ }; ++ ++ /************************/ ++ /* P9 Header */ ++ /************************/ ++ ++ /* P9_01 GND */ ++ ++ /* P9_02 GND */ ++ ++ /* P9_03 3V3 */ ++ ++ /* P9_04 3V3 */ ++ ++ /* P9_05 VDD_5V */ ++ ++ /* P9_06 VDD_5V */ ++ ++ /* P9_07 SYS_5V */ ++ ++ /* P9_08 SYS_5V */ ++ ++ /* P9_09 PWR_BUT */ ++ ++ /* P9_10 RSTn */ ++ ++ /* P9_11 (ZCZ ball T17) */ ++ P9_11_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; ++ pinctrl-0 = <&P9_11_default_pin>; ++ pinctrl-1 = <&P9_11_gpio_pin>; ++ pinctrl-2 = <&P9_11_gpio_pu_pin>; ++ pinctrl-3 = <&P9_11_gpio_pd_pin>; ++ pinctrl-4 = <&P9_11_uart_pin>; ++ }; ++ ++ /* P9_12 (ZCZ ball U18) */ ++ P9_12_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P9_12_default_pin>; ++ pinctrl-1 = <&P9_12_gpio_pin>; ++ pinctrl-2 = <&P9_12_gpio_pu_pin>; ++ pinctrl-3 = <&P9_12_gpio_pd_pin>; ++ }; ++ ++ /* P9_13 (ZCZ ball U17) */ ++ P9_13_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; ++ pinctrl-0 = <&P9_13_default_pin>; ++ pinctrl-1 = <&P9_13_gpio_pin>; ++ pinctrl-2 = <&P9_13_gpio_pu_pin>; ++ pinctrl-3 = <&P9_13_gpio_pd_pin>; ++ pinctrl-4 = <&P9_13_uart_pin>; ++ }; ++ ++ /* P9_14 (ZCZ ball U14) */ ++ P9_14_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_14_default_pin>; ++ pinctrl-1 = <&P9_14_gpio_pin>; ++ pinctrl-2 = <&P9_14_gpio_pu_pin>; ++ pinctrl-3 = <&P9_14_gpio_pd_pin>; ++ pinctrl-4 = <&P9_14_pwm_pin>; ++ }; ++ ++ /* P9_15 (ZCZ ball R13) */ ++ P9_15_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_15_default_pin>; ++ pinctrl-1 = <&P9_15_gpio_pin>; ++ pinctrl-2 = <&P9_15_gpio_pu_pin>; ++ pinctrl-3 = <&P9_15_gpio_pd_pin>; ++ pinctrl-4 = <&P9_15_pwm_pin>; ++ }; ++ ++ /* P9_16 (ZCZ ball T14) */ ++ P9_16_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_16_default_pin>; ++ pinctrl-1 = <&P9_16_gpio_pin>; ++ pinctrl-2 = <&P9_16_gpio_pu_pin>; ++ pinctrl-3 = <&P9_16_gpio_pd_pin>; ++ pinctrl-4 = <&P9_16_pwm_pin>; ++ }; ++ ++ /* P9_17 (ZCZ ball A16) */ ++ P9_17_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "i2c", "pwm", "pru_uart"; ++ pinctrl-0 = <&P9_17_default_pin>; ++ pinctrl-1 = <&P9_17_gpio_pin>; ++ pinctrl-2 = <&P9_17_gpio_pu_pin>; ++ pinctrl-3 = <&P9_17_gpio_pd_pin>; ++ pinctrl-4 = <&P9_17_spi_cs_pin>; ++ pinctrl-5 = <&P9_17_i2c_pin>; ++ pinctrl-6 = <&P9_17_pwm_pin>; ++ pinctrl-7 = <&P9_17_pru_uart_pin>; ++ }; ++ ++ /* P9_18 (ZCZ ball B16) */ ++ P9_18_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm", "pru_uart"; ++ pinctrl-0 = <&P9_18_default_pin>; ++ pinctrl-1 = <&P9_18_gpio_pin>; ++ pinctrl-2 = <&P9_18_gpio_pu_pin>; ++ pinctrl-3 = <&P9_18_gpio_pd_pin>; ++ pinctrl-4 = <&P9_18_spi_pin>; ++ pinctrl-5 = <&P9_18_i2c_pin>; ++ pinctrl-6 = <&P9_18_pwm_pin>; ++ pinctrl-7 = <&P9_18_pru_uart_pin>; ++ }; ++ ++ /* P9_19 (ZCZ ball D17) i2c */ ++ P9_19_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart", "timer"; ++ pinctrl-0 = <&P9_19_default_pin>; ++ pinctrl-1 = <&P9_19_gpio_pin>; ++ pinctrl-2 = <&P9_19_gpio_pu_pin>; ++ pinctrl-3 = <&P9_19_gpio_pd_pin>; ++ pinctrl-4 = <&P9_19_spi_cs_pin>; ++ pinctrl-5 = <&P9_19_can_pin>; ++ pinctrl-6 = <&P9_19_i2c_pin>; ++ pinctrl-7 = <&P9_19_pru_uart_pin>; ++ pinctrl-8 = <&P9_19_timer_pin>; ++ }; ++ ++ /* P9_20 (ZCZ ball D18) i2c */ ++ P9_20_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart", "timer"; ++ pinctrl-0 = <&P9_20_default_pin>; ++ pinctrl-1 = <&P9_20_gpio_pin>; ++ pinctrl-2 = <&P9_20_gpio_pu_pin>; ++ pinctrl-3 = <&P9_20_gpio_pd_pin>; ++ pinctrl-4 = <&P9_20_spi_cs_pin>; ++ pinctrl-5 = <&P9_20_can_pin>; ++ pinctrl-6 = <&P9_20_i2c_pin>; ++ pinctrl-7 = <&P9_20_pru_uart_pin>; ++ pinctrl-8 = <&P9_20_timer_pin>; ++ }; ++ ++ /* P9_21 (ZCZ ball B17) */ ++ P9_21_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm", "pru_uart"; ++ pinctrl-0 = <&P9_21_default_pin>; ++ pinctrl-1 = <&P9_21_gpio_pin>; ++ pinctrl-2 = <&P9_21_gpio_pu_pin>; ++ pinctrl-3 = <&P9_21_gpio_pd_pin>; ++ pinctrl-4 = <&P9_21_spi_pin>; ++ pinctrl-5 = <&P9_21_uart_pin>; ++ pinctrl-6 = <&P9_21_i2c_pin>; ++ pinctrl-7 = <&P9_21_pwm_pin>; ++ pinctrl-8 = <&P9_21_pru_uart_pin>; ++ }; ++ ++ /* P9_22 (ZCZ ball A17) */ ++ P9_22_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "uart", "i2c", "pwm", "pru_uart"; ++ pinctrl-0 = <&P9_22_default_pin>; ++ pinctrl-1 = <&P9_22_gpio_pin>; ++ pinctrl-2 = <&P9_22_gpio_pu_pin>; ++ pinctrl-3 = <&P9_22_gpio_pd_pin>; ++ pinctrl-4 = <&P9_22_spi_sclk_pin>; ++ pinctrl-5 = <&P9_22_uart_pin>; ++ pinctrl-6 = <&P9_22_i2c_pin>; ++ pinctrl-7 = <&P9_22_pwm_pin>; ++ pinctrl-8 = <&P9_22_pru_uart_pin>; ++ }; ++ ++ /* P9_23 (ZCZ ball V14) */ ++ P9_23_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_23_default_pin>; ++ pinctrl-1 = <&P9_23_gpio_pin>; ++ pinctrl-2 = <&P9_23_gpio_pu_pin>; ++ pinctrl-3 = <&P9_23_gpio_pd_pin>; ++ pinctrl-4 = <&P9_23_pwm_pin>; ++ }; ++ ++ /* P9_24 (ZCZ ball D15) */ ++ P9_24_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin"; ++ pinctrl-0 = <&P9_24_default_pin>; ++ pinctrl-1 = <&P9_24_gpio_pin>; ++ pinctrl-2 = <&P9_24_gpio_pu_pin>; ++ pinctrl-3 = <&P9_24_gpio_pd_pin>; ++ pinctrl-4 = <&P9_24_uart_pin>; ++ pinctrl-5 = <&P9_24_can_pin>; ++ pinctrl-6 = <&P9_24_i2c_pin>; ++ pinctrl-7 = <&P9_24_pru_uart_pin>; ++ pinctrl-8 = <&P9_24_pruin_pin>; ++ }; ++ ++ /* P9_25 (ZCZ ball A14) audio */ ++ P9_25_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_25_default_pin>; ++ pinctrl-1 = <&P9_25_gpio_pin>; ++ pinctrl-2 = <&P9_25_gpio_pu_pin>; ++ pinctrl-3 = <&P9_25_gpio_pd_pin>; ++ pinctrl-4 = <&P9_25_eqep_pin>; ++ pinctrl-5 = <&P9_25_pruout_pin>; ++ pinctrl-6 = <&P9_25_pruin_pin>; ++ }; ++ ++ /* P9_26 (ZCZ ball D16) */ ++ P9_26_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin"; ++ pinctrl-0 = <&P9_26_default_pin>; ++ pinctrl-1 = <&P9_26_gpio_pin>; ++ pinctrl-2 = <&P9_26_gpio_pu_pin>; ++ pinctrl-3 = <&P9_26_gpio_pd_pin>; ++ pinctrl-4 = <&P9_26_uart_pin>; ++ pinctrl-5 = <&P9_26_can_pin>; ++ pinctrl-6 = <&P9_26_i2c_pin>; ++ pinctrl-7 = <&P9_26_pru_uart_pin>; ++ pinctrl-8 = <&P9_26_pruin_pin>; ++ }; ++ ++ /* P9_27 (ZCZ ball C13) */ ++ P9_27_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_27_default_pin>; ++ pinctrl-1 = <&P9_27_gpio_pin>; ++ pinctrl-2 = <&P9_27_gpio_pu_pin>; ++ pinctrl-3 = <&P9_27_gpio_pd_pin>; ++ pinctrl-4 = <&P9_27_eqep_pin>; ++ pinctrl-5 = <&P9_27_pruout_pin>; ++ pinctrl-6 = <&P9_27_pruin_pin>; ++ }; ++ ++ /* P9_28 (ZCZ ball C12) audio */ ++ P9_28_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "pwm", "pwm2", "pruout", "pruin"; ++ pinctrl-0 = <&P9_28_default_pin>; ++ pinctrl-1 = <&P9_28_gpio_pin>; ++ pinctrl-2 = <&P9_28_gpio_pu_pin>; ++ pinctrl-3 = <&P9_28_gpio_pd_pin>; ++ pinctrl-4 = <&P9_28_spi_cs_pin>; ++ pinctrl-5 = <&P9_28_pwm_pin>; ++ pinctrl-6 = <&P9_28_pwm2_pin>; ++ pinctrl-7 = <&P9_28_pruout_pin>; ++ pinctrl-8 = <&P9_28_pruin_pin>; ++ }; ++ ++ /* P9_29 (ZCZ ball B13) audio */ ++ P9_29_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P9_29_default_pin>; ++ pinctrl-1 = <&P9_29_gpio_pin>; ++ pinctrl-2 = <&P9_29_gpio_pu_pin>; ++ pinctrl-3 = <&P9_29_gpio_pd_pin>; ++ pinctrl-4 = <&P9_29_spi_pin>; ++ pinctrl-5 = <&P9_29_pwm_pin>; ++ pinctrl-6 = <&P9_29_pruout_pin>; ++ pinctrl-7 = <&P9_29_pruin_pin>; ++ }; ++ ++ /* P9_30 (ZCZ ball D12) */ ++ P9_30_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P9_30_default_pin>; ++ pinctrl-1 = <&P9_30_gpio_pin>; ++ pinctrl-2 = <&P9_30_gpio_pu_pin>; ++ pinctrl-3 = <&P9_30_gpio_pd_pin>; ++ pinctrl-4 = <&P9_30_spi_pin>; ++ pinctrl-5 = <&P9_30_pwm_pin>; ++ pinctrl-6 = <&P9_30_pruout_pin>; ++ pinctrl-7 = <&P9_30_pruin_pin>; ++ }; ++ ++ /* P9_31 (ZCZ ball A13) audio */ ++ P9_31_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P9_31_default_pin>; ++ pinctrl-1 = <&P9_31_gpio_pin>; ++ pinctrl-2 = <&P9_31_gpio_pu_pin>; ++ pinctrl-3 = <&P9_31_gpio_pd_pin>; ++ pinctrl-4 = <&P9_31_spi_sclk_pin>; ++ pinctrl-5 = <&P9_31_pwm_pin>; ++ pinctrl-6 = <&P9_31_pruout_pin>; ++ pinctrl-7 = <&P9_31_pruin_pin>; ++ }; ++ ++ /* P9_32 VADC */ ++ ++ /* P9_33 (ZCZ ball C8) AIN4 */ ++ ++ /* P9_34 AGND */ ++ ++ /* P9_35 (ZCZ ball A8) AIN6 */ ++ ++ /* P9_36 (ZCZ ball B8) AIN5 */ ++ ++ /* P9_37 (ZCZ ball B7) AIN2 */ ++ ++ /* P9_38 (ZCZ ball A7) AIN3 */ ++ ++ /* P9_39 (ZCZ ball B6) AIN0 */ ++ ++ /* P9_40 (ZCZ ball C7) AIN1 */ ++ ++ /* P9_41 (ZCZ ball D14) */ ++ P9_41_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer", "pruin"; ++ pinctrl-0 = <&P9_41_default_pin>; ++ pinctrl-1 = <&P9_41_gpio_pin>; ++ pinctrl-2 = <&P9_41_gpio_pu_pin>; ++ pinctrl-3 = <&P9_41_gpio_pd_pin>; ++ pinctrl-4 = <&P9_41_timer_pin>; ++ pinctrl-5 = <&P9_41_pruin_pin>; ++ }; ++ ++ /* P9_41.1 */ ++ /* P9_91 (ZCZ ball D13) */ ++ P9_91_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_91_default_pin>; ++ pinctrl-1 = <&P9_91_gpio_pin>; ++ pinctrl-2 = <&P9_91_gpio_pu_pin>; ++ pinctrl-3 = <&P9_91_gpio_pd_pin>; ++ pinctrl-4 = <&P9_91_eqep_pin>; ++ pinctrl-5 = <&P9_91_pruout_pin>; ++ pinctrl-6 = <&P9_91_pruin_pin>; ++ }; ++ ++ /* P9_42 (ZCZ ball C18) */ ++ P9_42_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "spi_sclk", "uart", "pwm", "pru_ecap_pwm"; ++ pinctrl-0 = <&P9_42_default_pin>; ++ pinctrl-1 = <&P9_42_gpio_pin>; ++ pinctrl-2 = <&P9_42_gpio_pu_pin>; ++ pinctrl-3 = <&P9_42_gpio_pd_pin>; ++ pinctrl-4 = <&P9_42_spi_cs_pin>; ++ pinctrl-5 = <&P9_42_spi_sclk_pin>; ++ pinctrl-6 = <&P9_42_uart_pin>; ++ pinctrl-7 = <&P9_42_pwm_pin>; ++ pinctrl-8 = <&P9_42_pru_ecap_pwm_pin>; ++ }; ++ ++ /* P9_42.1 */ ++ /* P9_92 (ZCZ ball B12) */ ++ P9_92_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_92_default_pin>; ++ pinctrl-1 = <&P9_92_gpio_pin>; ++ pinctrl-2 = <&P9_92_gpio_pu_pin>; ++ pinctrl-3 = <&P9_92_gpio_pd_pin>; ++ pinctrl-4 = <&P9_92_eqep_pin>; ++ pinctrl-5 = <&P9_92_pruout_pin>; ++ pinctrl-6 = <&P9_92_pruin_pin>; ++ }; ++ ++ /* P9_43 GND */ ++ ++ /* P9_44 GND */ ++ ++ /* P9_45 GND */ ++ ++ /* P9_46 GND */ ++ ++ cape-universal { ++ compatible = "gpio-of-helper"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ P8_03 { ++ gpio-name = "P8_03"; ++ gpio = <&gpio1 6 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_04 { ++ gpio-name = "P8_04"; ++ gpio = <&gpio1 7 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_05 { ++ gpio-name = "P8_05"; ++ gpio = <&gpio1 2 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_06 { ++ gpio-name = "P8_06"; ++ gpio = <&gpio1 3 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_07 { ++ gpio-name = "P8_07"; ++ gpio = <&gpio2 2 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_08 { ++ gpio-name = "P8_08"; ++ gpio = <&gpio2 3 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_09 { ++ gpio-name = "P8_09"; ++ gpio = <&gpio2 5 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_10 { ++ gpio-name = "P8_10"; ++ gpio = <&gpio2 4 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_11 { ++ gpio-name = "P8_11"; ++ gpio = <&gpio1 13 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_12 { ++ gpio-name = "P8_12"; ++ gpio = <&gpio1 12 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_13 { ++ gpio-name = "P8_13"; ++ gpio = <&gpio0 23 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_14 { ++ gpio-name = "P8_14"; ++ gpio = <&gpio0 26 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_15 { ++ gpio-name = "P8_15"; ++ gpio = <&gpio1 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_16 { ++ gpio-name = "P8_16"; ++ gpio = <&gpio1 14 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_17 { ++ gpio-name = "P8_17"; ++ gpio = <&gpio0 27 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_18 { ++ gpio-name = "P8_18"; ++ gpio = <&gpio2 1 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_19 { ++ gpio-name = "P8_19"; ++ gpio = <&gpio0 22 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_20 { ++ gpio-name = "P8_20"; ++ gpio = <&gpio1 31 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_21 { ++ gpio-name = "P8_21"; ++ gpio = <&gpio1 30 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_22 { ++ gpio-name = "P8_22"; ++ gpio = <&gpio1 5 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_23 { ++ gpio-name = "P8_23"; ++ gpio = <&gpio1 4 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_24 { ++ gpio-name = "P8_24"; ++ gpio = <&gpio1 1 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_25 { ++ gpio-name = "P8_25"; ++ gpio = <&gpio1 0 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_26 { ++ gpio-name = "P8_26"; ++ gpio = <&gpio1 29 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_27 { ++ gpio-name = "P8_27"; ++ gpio = <&gpio2 22 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_28 { ++ gpio-name = "P8_28"; ++ gpio = <&gpio2 24 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_29 { ++ gpio-name = "P8_29"; ++ gpio = <&gpio2 23 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_30 { ++ gpio-name = "P8_30"; ++ gpio = <&gpio2 25 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_31 { ++ gpio-name = "P8_31"; ++ gpio = <&gpio0 10 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_32 { ++ gpio-name = "P8_32"; ++ gpio = <&gpio0 11 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_33 { ++ gpio-name = "P8_33"; ++ gpio = <&gpio0 9 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_34 { ++ gpio-name = "P8_34"; ++ gpio = <&gpio2 17 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_35 { ++ gpio-name = "P8_35"; ++ gpio = <&gpio0 8 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_36 { ++ gpio-name = "P8_36"; ++ gpio = <&gpio2 16 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_37 { ++ gpio-name = "P8_37"; ++ gpio = <&gpio2 14 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_38 { ++ gpio-name = "P8_38"; ++ gpio = <&gpio2 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_39 { ++ gpio-name = "P8_39"; ++ gpio = <&gpio2 12 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_40 { ++ gpio-name = "P8_40"; ++ gpio = <&gpio2 13 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_41 { ++ gpio-name = "P8_41"; ++ gpio = <&gpio2 10 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_42 { ++ gpio-name = "P8_42"; ++ gpio = <&gpio2 11 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_43 { ++ gpio-name = "P8_43"; ++ gpio = <&gpio2 8 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_44 { ++ gpio-name = "P8_44"; ++ gpio = <&gpio2 9 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_45 { ++ gpio-name = "P8_45"; ++ gpio = <&gpio2 6 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_46 { ++ gpio-name = "P8_46"; ++ gpio = <&gpio2 7 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_11 { ++ gpio-name = "P9_11"; ++ gpio = <&gpio0 30 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_12 { ++ gpio-name = "P9_12"; ++ gpio = <&gpio1 28 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_13 { ++ gpio-name = "P9_13"; ++ gpio = <&gpio0 31 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_14 { ++ gpio-name = "P9_14"; ++ gpio = <&gpio1 18 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_15 { ++ gpio-name = "P9_15"; ++ gpio = <&gpio1 16 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_16 { ++ gpio-name = "P9_16"; ++ gpio = <&gpio1 19 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_17 { ++ gpio-name = "P9_17"; ++ gpio = <&gpio0 5 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_18 { ++ gpio-name = "P9_18"; ++ gpio = <&gpio0 4 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_19 { ++ gpio-name = "P9_19"; ++ gpio = <&gpio0 13 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_20 { ++ gpio-name = "P9_20"; ++ gpio = <&gpio0 12 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_21 { ++ gpio-name = "P9_21"; ++ gpio = <&gpio0 3 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_22 { ++ gpio-name = "P9_22"; ++ gpio = <&gpio0 2 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_23 { ++ gpio-name = "P9_23"; ++ gpio = <&gpio1 17 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_24 { ++ gpio-name = "P9_24"; ++ gpio = <&gpio0 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_25 { ++ gpio-name = "P9_25"; ++ gpio = <&gpio3 21 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_26 { ++ gpio-name = "P9_26"; ++ gpio = <&gpio0 14 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_27 { ++ gpio-name = "P9_27"; ++ gpio = <&gpio3 19 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_28 { ++ gpio-name = "P9_28"; ++ gpio = <&gpio3 17 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_29 { ++ gpio-name = "P9_29"; ++ gpio = <&gpio3 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_30 { ++ gpio-name = "P9_30"; ++ gpio = <&gpio3 16 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_31 { ++ gpio-name = "P9_31"; ++ gpio = <&gpio3 14 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_41 { ++ gpio-name = "P9_41"; ++ gpio = <&gpio0 20 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_91 { ++ gpio-name = "P9_91"; ++ gpio = <&gpio3 20 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_42 { ++ gpio-name = "P9_42"; ++ gpio = <&gpio0 7 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_92 { ++ gpio-name = "P9_92"; ++ gpio = <&gpio3 18 0>; ++ input; ++ dir-changeable; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bone.dts b/arch/arm/boot/dts/ti/omap/am335x-bone.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-bone.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bone.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -10,6 +10,11 @@ + / { + model = "TI AM335x BeagleBone"; + compatible = "ti,am335x-bone", "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-bone.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; + + &ldo3_reg { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-common.dtsi +--- a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-common.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-common.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -34,6 +34,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; ++ symlink = "bone/uart/2"; + }; + + &rtc { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bonegreen.dts b/arch/arm/boot/dts/ti/omap/am335x-bonegreen.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-bonegreen.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bonegreen.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -11,4 +11,157 @@ + / { + model = "TI AM335x BeagleBone Green"; + compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-bonegreen.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; ++ ++&gpio0 { ++ gpio-line-names = ++ "[mdio_data]", ++ "[mdio_clk]", ++ "P9_22 [spi0_sclk]", ++ "P9_21 [spi0_d0]", ++ "P9_18 [spi0_d1]", ++ "P9_17 [spi0_cs0]", ++ "[mmc0_cd]", ++ "P9_42A [ecappwm0]", ++ "P8_35 [lcd d12]", ++ "P8_33 [lcd d13]", ++ "P8_31 [lcd d14]", ++ "P8_32 [lcd d15]", ++ "P9_20 [i2c2_sda]", ++ "P9_19 [i2c2_scl]", ++ "P9_26 [uart1_rxd]", ++ "P9_24 [uart1_txd]", ++ "[rmii1_txd3]", ++ "[rmii1_txd2]", ++ "[usb0_drvvbus]", ++ "[hdmi cec]", ++ "P9_41B", ++ "[rmii1_txd1]", ++ "P8_19 [ehrpwm2a]", ++ "P8_13 [ehrpwm2b]", ++ "NC", ++ "NC", ++ "P8_14", ++ "P8_17", ++ "[rmii1_txd0]", ++ "[rmii1_refclk]", ++ "P9_11 [uart4_rxd]", ++ "P9_13 [uart4_txd]"; ++}; ++ ++&gpio1 { ++ gpio-line-names = ++ "P8_25 [mmc1_dat0]", ++ "[mmc1_dat1]", ++ "P8_5 [mmc1_dat2]", ++ "P8_6 [mmc1_dat3]", ++ "P8_23 [mmc1_dat4]", ++ "P8_22 [mmc1_dat5]", ++ "P8_3 [mmc1_dat6]", ++ "P8_4 [mmc1_dat7]", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "P8_12", ++ "P8_11", ++ "P8_16", ++ "P8_15", ++ "P9_15A", ++ "P9_23", ++ "P9_14 [ehrpwm1a]", ++ "P9_16 [ehrpwm1b]", ++ "[emmc rst]", ++ "[usr0 led]", ++ "[usr1 led]", ++ "[usr2 led]", ++ "[usr3 led]", ++ "[hdmi irq]", ++ "[usb vbus oc]", ++ "[hdmi audio]", ++ "P9_12", ++ "P8_26", ++ "P8_21 [emmc]", ++ "P8_20 [emmc]"; ++}; ++ ++&gpio2 { ++ gpio-line-names = ++ "P9_15B", ++ "P8_18", ++ "P8_7", ++ "P8_8", ++ "P8_10", ++ "P8_9", ++ "P8_45", ++ "P8_46", ++ "P8_43", ++ "P8_44", ++ "P8_41", ++ "P8_42", ++ "P8_39", ++ "P8_40", ++ "P8_37", ++ "P8_38", ++ "P8_36", ++ "P8_34", ++ "[rmii1_rxd3]", ++ "[rmii1_rxd2]", ++ "[rmii1_rxd1]", ++ "[rmii1_rxd0]", ++ "P8_27", ++ "P8_29", ++ "P8_28", ++ "P8_30", ++ "[mmc0_dat3]", ++ "[mmc0_dat2]", ++ "[mmc0_dat1]", ++ "[mmc0_dat0]", ++ "[mmc0_clk]", ++ "[mmc0_cmd]"; ++}; ++ ++&gpio3 { ++ gpio-line-names = ++ "[mii col]", ++ "[mii crs]", ++ "[mii rx err]", ++ "[mii tx en]", ++ "[mii rx dv]", ++ "[i2c0 sda]", ++ "[i2c0 scl]", ++ "[jtag emu0]", ++ "[jtag emu1]", ++ "[mii tx clk]", ++ "[mii rx clk]", ++ "NC", ++ "NC", ++ "[usb vbus en]", ++ "P9_31 [spi1_sclk]", ++ "P9_29 [spi1_d0]", ++ "P9_30 [spi1_d1]", ++ "P9_28 [spi1_cs0]", ++ "P9_42B [ecappwm0]", ++ "P9_27", ++ "P9_41A", ++ "P9_25", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC", ++ "NC"; ++}; ++ ++&baseboard_eeprom { ++ vcc-supply = <&ldo4_reg>; ++}; +\ No newline at end of file +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-gateway.dts b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-gateway.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-gateway.dts 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-gateway.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,263 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++/dts-v1/; ++ ++#include "am33xx.dtsi" ++#include "am335x-bone-common.dtsi" ++#include "am335x-bonegreen-common.dtsi" ++#include ++ ++/ { ++ model = "SeeedStudio BeagleBone Green Gateway"; ++ compatible = "ti,am335x-bone-green-gateway", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ aliases { ++ rtc0 = &extrtc; ++ rtc1 = &rtc; ++ }; ++ ++ chosen { ++ base_dtb = "am335x-bonegreen-gateway.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ wl1835_bt = "S3-texas-300000"; ++ }; ++ ++ wlan_en_reg: fixedregulator@2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ startup-delay-us= <70000>; ++ ++ /* WL_EN */ ++ gpio = <&gpio3 9 0>; ++ enable-active-high; ++ }; ++ ++ leds { ++ pinctrl-names = "default"; ++ //pinctrl-0 = <&user_leds_s0>; ++ pinctrl-0 = <&user_leds_s0 &bt_pins>; ++ ++ compatible = "gpio-leds"; ++ ++ led2 { ++ label = "beaglebone:green:usr0"; ++ gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ default-state = "off"; ++ }; ++ ++ led3 { ++ label = "beaglebone:green:usr1"; ++ gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc0"; ++ default-state = "off"; ++ }; ++ ++ led4 { ++ label = "beaglebone:green:usr2"; ++ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "cpu0"; ++ default-state = "off"; ++ }; ++ ++ led5 { ++ label = "beaglebone:green:usr3"; ++ gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc1"; ++ default-state = "off"; ++ }; ++ ++ led6 { ++ label = "beaglebone:green:usr4"; ++ gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "netdev"; ++ default-state = "off"; ++ }; ++ ++ wl18xx_bt_en: led7 { ++ label = "wl18xx_bt_en"; ++ gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++}; ++ ++&cpu0_opp_table { ++ /* ++ * Octavo Systems: ++ * The EFUSE_SMA register is not programmed for any of the AM335x wafers ++ * we get and we are not programming them during our production test. ++ * Therefore, from a DEVICE_ID revision point of view, the silicon looks ++ * like it is Revision 2.1. However, from an EFUSE_SMA point of view for ++ * the HW OPP table, the silicon looks like it is Revision 1.0 (ie the ++ * EFUSE_SMA register reads as all zeros). ++ */ ++ oppnitro-1000000000 { ++ opp-supported-hw = <0x06 0x0100>; ++ }; ++}; ++ ++&am33xx_pinmux { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usbhost_pins>; ++ ++ user_leds_s0: user-leds-s0-pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a6.gpio1_22 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a7.gpio1_23 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a8.gpio1_24 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* WL_Active_LED / USR4 */ ++ >; ++ }; ++ ++ bt_pins: bt-pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gmii1_txd0.gpio0_28 - BT_EN */ ++ >; ++ }; ++ ++ mmc3_pins: mmc3-pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */ ++ >; ++ }; ++ ++ uart2_grove_pins: pinmux_uart2_grove_pins { ++ pinctrl-single,pins = < ++ AM33XX_IOPAD(0x90c, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6) ++ AM33XX_IOPAD(0x910, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6) ++ >; ++ }; ++ ++ uart3_pins: uart3-pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gmii1_rxd3.uart3_rxd */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* gmii1_rxd2.uart3_txd */ ++ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3) /* mdio_data.uart3_ctsn */ ++ AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* mdio_clk.uart3_rtsn */ ++ >; ++ }; ++ ++ usbhost_pins: pinmux_usbhost_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_txd1.gpio0[21] */ ++ >; ++ }; ++ ++ wl18xx_pins: wl18xx-pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gmii1_txclk.gpio3_9 WL_EN */ ++ AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_refclk.gpio0_29 WL_IRQ */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_rxclk.gpio3_10 LS_BUF_EN */ ++ >; ++ }; ++}; ++ ++&mac_sw { ++ /delete-property/pinctrl-names; ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-1; ++ status = "disabled"; ++}; ++ ++&mmc3 { ++ dmas = <&edma_xbar 12 0 1 ++ &edma_xbar 13 0 2>; ++ dma-names = "tx", "rx"; ++ status = "okay"; ++ vmmc-supply = <&wlan_en_reg>; ++ bus-width = <4>; ++ non-removable; ++ cap-power-off-card; ++ keep-power-in-suspend; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc3_pins &wl18xx_pins>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wlcore: wlcore@2 { ++ compatible = "ti,wl1835"; ++ reg = <2>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <29 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; ++ ++&uart2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart2_grove_pins>; ++ status = "okay"; ++}; ++ ++&uart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart3_pins>; ++ //pinctrl-0 = <&uart3_pins &bt_pins>; ++ status = "okay"; ++ ++ //bluetooth { ++ // compatible = "ti,wl1835-st"; ++ // enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>; ++ //}; ++}; ++ ++&i2c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ extrtc: rtc@68 { ++ compatible = "dallas,ds1340"; ++ reg = <0x68>; ++ }; ++}; ++ ++// (K16) gmii1_txd1.gpio0[21] ++&gpio0 { ++ usb-reset-hog { ++ gpio-hog; ++ gpios = <21 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "usb_reset"; ++ }; ++}; ++ ++&gpio3 { ++ ls-buf-en-hog { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LS_BUF_EN"; ++ }; ++}; ++ ++&usb1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hub@1 { ++ compatible = "usb424,9512"; ++ reg = <1>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ethernet: ethernet@1 { ++ compatible = "usb424,ec00"; ++ reg = <1>; ++ }; ++ }; ++}; ++ ++&baseboard_eeprom { ++ vcc-supply = <&ldo4_reg>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless-common-univ.dtsi b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless-common-univ.dtsi +--- a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless-common-univ.dtsi 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless-common-univ.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,2197 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++#include ++ ++&am33xx_pinmux { ++ ++/* macro: BONE_PIN( , , */ ++#define BONE_PIN(XX,ZZ,QQ) \ ++ XX##_##ZZ##_pin: pinmux_##XX##_##ZZ##_pin { pinctrl-single,pins = < QQ >; }; ++ ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ /* P8_01 GND */ ++ ++ /* P8_02 GND */ ++ ++ ++ /* P8_03 (ZCZ ball R9) gpmc_ad6 (emmc) */ ++ BONE_PIN(P8_03, default, P8_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_03, gpio, P8_03(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_03, gpio_pu, P8_03(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_03, gpio_pd, P8_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_04 (ZCZ ball T9) gpmc_ad7 (emmc) */ ++ BONE_PIN(P8_04, default, P8_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_04, gpio, P8_04(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_04, gpio_pu, P8_04(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_04, gpio_pd, P8_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_05 (ZCZ ball R8) gpmc_ad2 (emmc) */ ++ BONE_PIN(P8_05, default, P8_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_05, gpio, P8_05(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_05, gpio_pu, P8_05(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_05, gpio_pd, P8_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_06 (ZCZ ball T8) gpmc_ad3 (emmc) */ ++ BONE_PIN(P8_06, default, P8_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_06, gpio, P8_06(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_06, gpio_pu, P8_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_06, gpio_pd, P8_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_07 (ZCZ ball R7) gpmc_advn_ale (gpio2_2) */ ++ BONE_PIN(P8_07, default, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_07, gpio, P8_07(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_07, gpio_pu, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_07, gpio_pd, P8_07(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_07, timer, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_08 (ZCZ ball T7) gpmc_oen_ren (gpio2_3) */ ++ BONE_PIN(P8_08, default, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_08, gpio, P8_08(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_08, gpio_pu, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_08, gpio_pd, P8_08(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_08, timer, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_09 (ZCZ ball T6) gpmc_be0n_cle (gpio2_5) */ ++ BONE_PIN(P8_09, default, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_09, gpio, P8_09(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_09, gpio_pu, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_09, gpio_pd, P8_09(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_09, timer, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_10 (ZCZ ball U6) gpmc_wen (gpio2_4) */ ++ BONE_PIN(P8_10, default, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_10, gpio, P8_10(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_10, gpio_pu, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_10, gpio_pd, P8_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_10, timer, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_11 (ZCZ ball R12) gpmc_ad13 (gpio1_13) */ ++ BONE_PIN(P8_11, default, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, gpio, P8_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, gpio_pu, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, gpio_pd, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_11, eqep, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P8_11, pruout, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P8_12 (ZCZ ball T12) gpmc_ad12 (gpio1_12) */ ++ BONE_PIN(P8_12, default, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, gpio, P8_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, gpio_pu, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, gpio_pd, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_12, eqep, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P8_12, pruout, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P8_13 (ZCZ ball T10) gpmc_ad9 (gpio0_23) */ ++ BONE_PIN(P8_13, default, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_13, gpio, P8_13(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_13, gpio_pu, P8_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_13, gpio_pd, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_13, pwm, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_14 (ZCZ ball T11) wl1835: wl_en */ ++ ++ /* P8_15 (ZCZ ball U13) gpmc_ad15 (gpio1_15) */ ++ BONE_PIN(P8_15, default, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_15, gpio, P8_15(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_15, gpio_pu, P8_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_15, gpio_pd, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_15, eqep, P8_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P8_15, pru_ecap_pwm, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_15, pruin, P8_15(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_16 (ZCZ ball V13) gpmc_ad14 (gpio1_14) */ ++ BONE_PIN(P8_16, default, P8_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_16, gpio, P8_16(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_16, gpio_pu, P8_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_16, gpio_pd, P8_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_16, eqep, P8_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P8_16, pruin, P8_16(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_17 (ZCZ ball U12) wl1835: wl_irq */ ++ ++ /* P8_18 (ZCZ ball V12) gpmc_clk (gpio2_1) */ ++ BONE_PIN(P8_18, default, P8_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_18, gpio, P8_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_18, gpio_pu, P8_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_18, gpio_pd, P8_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_19 (ZCZ ball U10) gpmc_ad8 (gpio0_22) */ ++ BONE_PIN(P8_19, default, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_19, gpio, P8_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_19, gpio_pu, P8_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_19, gpio_pd, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_19, pwm, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_20 (ZCZ ball V9) gpmc_csn2 (emmc) */ ++ BONE_PIN(P8_20, default, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_20, gpio, P8_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_20, gpio_pu, P8_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_20, gpio_pd, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_20, pruout, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_20, pruin, P8_20(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_21 (ZCZ ball U9) gpmc_csn1 (emmc) */ ++ BONE_PIN(P8_21, default, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_21, gpio, P8_21(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_21, gpio_pu, P8_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_21, gpio_pd, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_21, pruout, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_21, pruin, P8_21(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_22 (ZCZ ball V8) gpmc_ad5 (emmc) */ ++ BONE_PIN(P8_22, default, P8_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_22, gpio, P8_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_22, gpio_pu, P8_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_22, gpio_pd, P8_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_23 (ZCZ ball U8) gpmc_ad4 (emmc) */ ++ BONE_PIN(P8_23, default, P8_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_23, gpio, P8_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_23, gpio_pu, P8_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_23, gpio_pd, P8_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_24 (ZCZ ball V7) gpmc_ad1 (emmc) */ ++ BONE_PIN(P8_24, default, P8_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_24, gpio, P8_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_24, gpio_pu, P8_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_24, gpio_pd, P8_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_25 (ZCZ ball U7) gpmc_ad0 (emmc) */ ++ BONE_PIN(P8_25, default, P8_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_25, gpio, P8_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_25, gpio_pu, P8_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_25, gpio_pd, P8_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P8_26 (ZCZ ball V6) gpio-hog wl1835 */ ++ ++ /* P8_27 (ZCZ ball U5) lcd_vsync (hdmi) */ ++ BONE_PIN(P8_27, default, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_27, gpio, P8_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_27, gpio_pu, P8_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_27, gpio_pd, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_27, pruout, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_27, pruin, P8_27(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_28 (ZCZ ball V5) lcd_pclk (hdmi) */ ++ BONE_PIN(P8_28, default, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_28, gpio, P8_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_28, gpio_pu, P8_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_28, gpio_pd, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_28, pruout, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_28, pruin, P8_28(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_29 (ZCZ ball R5) lcd_hsync (hdmi) */ ++ BONE_PIN(P8_29, default, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_29, gpio, P8_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_29, gpio_pu, P8_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_29, gpio_pd, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_29, pruout, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_29, pruin, P8_29(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_30 (ZCZ ball R6) lcd_ac_bias_en (hdmi) */ ++ BONE_PIN(P8_30, default, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_30, gpio, P8_30(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_30, gpio_pu, P8_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_30, gpio_pd, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_30, pruout, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_30, pruin, P8_30(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_31 (ZCZ ball V4) lcd_data14 (hdmi) */ ++ BONE_PIN(P8_31, default, P8_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_31, gpio, P8_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_31, gpio_pu, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_31, gpio_pd, P8_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_31, eqep, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P8_31, uart, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_32 (ZCZ ball T5) lcd_data15 (hdmi) */ ++ BONE_PIN(P8_32, default, P8_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_32, gpio, P8_32(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_32, gpio_pu, P8_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_32, gpio_pd, P8_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_32, eqep, P8_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_33 (ZCZ ball V3) lcd_data13 (hdmi) */ ++ BONE_PIN(P8_33, default, P8_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_33, gpio, P8_33(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_33, gpio_pu, P8_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_33, gpio_pd, P8_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_33, eqep, P8_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_34 (ZCZ ball U4) lcd_data11 (hdmi) */ ++ BONE_PIN(P8_34, default, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_34, gpio, P8_34(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_34, gpio_pu, P8_34(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_34, gpio_pd, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_34, pwm, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_35 (ZCZ ball V2) lcd_data12 (hdmi) */ ++ BONE_PIN(P8_35, default, P8_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_35, gpio, P8_35(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_35, gpio_pu, P8_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_35, gpio_pd, P8_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_35, eqep, P8_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_36 (ZCZ ball U3) lcd_data10 (hdmi) */ ++ BONE_PIN(P8_36, default, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_36, gpio, P8_36(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_36, gpio_pu, P8_36(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_36, gpio_pd, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_36, pwm, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2)) ++ ++ /* P8_37 (ZCZ ball U1) lcd_data8 (hdmi) */ ++ BONE_PIN(P8_37, default, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_37, gpio, P8_37(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_37, gpio_pu, P8_37(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_37, gpio_pd, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_37, pwm, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P8_37, uart, P8_37(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_38 (ZCZ ball U2) lcd_data9 (hdmi) */ ++ BONE_PIN(P8_38, default, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_38, gpio, P8_38(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_38, gpio_pu, P8_38(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_38, gpio_pd, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_38, pwm, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P8_38, uart, P8_38(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P8_39 (ZCZ ball T3) lcd_data6 (hdmi) */ ++ BONE_PIN(P8_39, default, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_39, gpio, P8_39(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_39, gpio_pu, P8_39(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_39, gpio_pd, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_39, eqep, P8_39(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_39, pruout, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_39, pruin, P8_39(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_40 (ZCZ ball T4) lcd_data7 (hdmi) */ ++ BONE_PIN(P8_40, default, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_40, gpio, P8_40(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_40, gpio_pu, P8_40(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_40, gpio_pd, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_40, eqep, P8_40(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_40, pruout, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_40, pruin, P8_40(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_41 (ZCZ ball T1) lcd_data4 (hdmi) */ ++ BONE_PIN(P8_41, default, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_41, gpio, P8_41(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_41, gpio_pu, P8_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_41, gpio_pd, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_41, eqep, P8_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_41, pruout, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_41, pruin, P8_41(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_42 (ZCZ ball T2) lcd_data5 (hdmi) */ ++ BONE_PIN(P8_42, default, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_42, gpio, P8_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_42, gpio_pu, P8_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_42, gpio_pd, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_42, eqep, P8_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_42, pruout, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_42, pruin, P8_42(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_43 (ZCZ ball R3) lcd_data2 (hdmi) */ ++ BONE_PIN(P8_43, default, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_43, gpio, P8_43(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_43, gpio_pu, P8_43(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_43, gpio_pd, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_43, pwm, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_43, pruout, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_43, pruin, P8_43(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_44 (ZCZ ball R4) lcd_data3 (hdmi) */ ++ BONE_PIN(P8_44, default, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_44, gpio, P8_44(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_44, gpio_pu, P8_44(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_44, gpio_pd, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_44, pwm, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_44, pruout, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_44, pruin, P8_44(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_45 (ZCZ ball R1) lcd_data0 (hdmi) */ ++ BONE_PIN(P8_45, default, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_45, gpio, P8_45(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_45, gpio_pu, P8_45(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_45, gpio_pd, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_45, pwm, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_45, pruout, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_45, pruin, P8_45(PIN_INPUT | MUX_MODE6)) ++ ++ /* P8_46 (ZCZ ball R2) lcd_data1 (hdmi) */ ++ BONE_PIN(P8_46, default, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_46, gpio, P8_46(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_46, gpio_pu, P8_46(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_46, gpio_pd, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P8_46, pwm, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P8_46, pruout, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P8_46, pruin, P8_46(PIN_INPUT | MUX_MODE6)) ++ ++ /************************/ ++ /* P9 Header */ ++ /************************/ ++ ++ /* P9_01 GND */ ++ ++ /* P9_02 GND */ ++ ++ /* P9_03 3V3 */ ++ ++ /* P9_04 3V3 */ ++ ++ /* P9_05 VDD_5V */ ++ ++ /* P9_06 VDD_5V */ ++ ++ /* P9_07 SYS_5V */ ++ ++ /* P9_08 SYS_5V */ ++ ++ /* P9_09 PWR_BUT */ ++ ++ /* P9_10 RSTn */ ++ ++ /* P9_11 (ZCZ ball T17) gpmc_wait0 (gpio0_30) */ ++ BONE_PIN(P9_11, default, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_11, gpio, P9_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_11, gpio_pu, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_11, gpio_pd, P9_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_11, uart, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_12 (ZCZ ball U18) gpmc_be1n (gpio1_28) */ ++ BONE_PIN(P9_12, default, P9_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_12, gpio, P9_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_12, gpio_pu, P9_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_12, gpio_pd, P9_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ ++ /* P9_13 (ZCZ ball U17) gpmc_wpn (gpio0_31) */ ++ BONE_PIN(P9_13, default, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_13, gpio, P9_13(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_13, gpio_pu, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_13, gpio_pd, P9_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_13, uart, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_14 (ZCZ ball U14) gpmc_a2 (gpio1_18) */ ++ BONE_PIN(P9_14, default, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, gpio, P9_14(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, gpio_pu, P9_14(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, gpio_pd, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_14, pwm, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_15 (ZCZ ball R13) gpmc_a0 (gpio1_16) */ ++ BONE_PIN(P9_15, default, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_15, gpio, P9_15(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_15, gpio_pu, P9_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_15, gpio_pd, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_15, pwm, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_16 (ZCZ ball T14) gpmc_a3 (gpio1_19) */ ++ BONE_PIN(P9_16, default, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_16, gpio, P9_16(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_16, gpio_pu, P9_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_16, gpio_pd, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_16, pwm, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_17 (ZCZ ball A16) spi0_cs0 (gpio0_5) */ ++ BONE_PIN(P9_17, default, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_17, gpio, P9_17(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_17, gpio_pu, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_17, gpio_pd, P9_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_17, spi_cs, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_17, i2c, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_17, pwm, P9_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_17, pru_uart, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P9_18 (ZCZ ball B16) spi0_d1 (gpio0_4) */ ++ BONE_PIN(P9_18, default, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_18, gpio, P9_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_18, gpio_pu, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_18, gpio_pd, P9_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_18, spi, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_18, i2c, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_18, pwm, P9_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_18, pru_uart, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P9_19 (ZCZ ball D17) uart1_rtsn (i2c2_scl) */ ++ BONE_PIN(P9_19, default, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_19, gpio, P9_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_19, gpio_pu, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_19, gpio_pd, P9_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_19, timer, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_19, can, P9_19(PIN_INPUT_PULLUP | MUX_MODE2)) ++ BONE_PIN(P9_19, i2c, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_19, spi_cs, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P9_19, pru_uart, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5)) ++ ++ /* P9_20 (ZCZ ball D18) uart1_ctsn (i2c2_sda) */ ++ BONE_PIN(P9_20, default, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_20, gpio, P9_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_20, gpio_pu, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_20, gpio_pd, P9_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_20, timer, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_20, can, P9_20(PIN_OUTPUT_PULLUP | MUX_MODE2)) ++ BONE_PIN(P9_20, i2c, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_20, spi_cs, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P9_20, pru_uart, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5)) ++ ++ /* P9_21 (ZCZ ball B17) spi0_d0 (gpio0_3) */ ++ BONE_PIN(P9_21, default, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_21, gpio, P9_21(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_21, gpio_pu, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_21, gpio_pd, P9_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_21, spi, P9_21(PIN_INPUT_PULLUP | MUX_MODE0)) ++ BONE_PIN(P9_21, uart, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_21, i2c, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_21, pwm, P9_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_21, pru_uart, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P9_22 (ZCZ ball A17) spi0_sclk (gpio0_2) */ ++ BONE_PIN(P9_22, default, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_22, gpio, P9_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_22, gpio_pu, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_22, gpio_pd, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_22, spi_sclk, P9_22(PIN_INPUT_PULLUP | MUX_MODE0)) ++ BONE_PIN(P9_22, uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_22, i2c, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_22, pwm, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_22, pru_uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ ++ /* P9_23 (ZCZ ball V14) gpmc_a1 (gpio1_17) */ ++ BONE_PIN(P9_23, default, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, gpio, P9_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, gpio_pu, P9_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, gpio_pd, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_23, pwm, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6)) ++ ++ /* P9_24 (ZCZ ball D15) uart1_txd (gpio0_15) */ ++ BONE_PIN(P9_24, default, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_24, gpio, P9_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_24, gpio_pu, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_24, gpio_pd, P9_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_24, uart, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_24, can, P9_24(PIN_INPUT_PULLUP | MUX_MODE2)) ++ BONE_PIN(P9_24, i2c, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_24, pru_uart, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_24, pruin, P9_24(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_25 (ZCZ ball A14) mcasp0_ahclkx (audio) */ ++ BONE_PIN(P9_25, default, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_25, gpio, P9_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_25, gpio_pu, P9_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_25, gpio_pd, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_25, eqep, P9_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_25, pruout, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_25, pruin, P9_25(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_26 (ZCZ ball D16) uart1_rxd (gpio0_14) */ ++ BONE_PIN(P9_26, default, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_26, gpio, P9_26(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_26, gpio_pu, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_26, gpio_pd, P9_26(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_26, uart, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_26, can, P9_26(PIN_OUTPUT_PULLUP | MUX_MODE2)) ++ BONE_PIN(P9_26, i2c, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_26, pru_uart, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_26, pruin, P9_26(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_27 (ZCZ ball C13) mcasp0_fsr (gpio3_19) */ ++ BONE_PIN(P9_27, default, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_27, gpio, P9_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_27, gpio_pu, P9_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_27, gpio_pd, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_27, eqep, P9_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_27, pruout, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_27, pruin, P9_27(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_28 (ZCZ ball C12) mcasp0_ahclkr (audio) */ ++ BONE_PIN(P9_28, default, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_28, gpio, P9_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_28, gpio_pu, P9_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_28, gpio_pd, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_28, pwm, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_28, spi_cs, P9_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_28, pwm2, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P9_28, pruout, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_28, pruin, P9_28(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_29 (ZCZ ball B13) mcasp0_fsx (audio) */ ++ BONE_PIN(P9_29, default, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_29, gpio, P9_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_29, gpio_pu, P9_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_29, gpio_pd, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_29, pwm, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_29, spi, P9_29(PIN_INPUT_PULLUP | MUX_MODE3)) ++ BONE_PIN(P9_29, pruout, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_29, pruin, P9_29(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_30 (ZCZ ball D12) gpio-hog wl1835 */ ++ ++ /* P9_31 (ZCZ ball A13) mcasp0_aclkx (audio) */ ++ BONE_PIN(P9_31, default, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_31, gpio, P9_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_31, gpio_pu, P9_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_31, gpio_pd, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_31, pwm, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_31, spi_sclk, P9_31(PIN_INPUT_PULLUP | MUX_MODE3)) ++ BONE_PIN(P9_31, pruout, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_31, pruin, P9_31(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_32 VADC */ ++ ++ /* P9_33 (ZCZ ball C8) AIN4 */ ++ ++ /* P9_34 AGND */ ++ ++ /* P9_35 (ZCZ ball A8) AIN6 */ ++ ++ /* P9_36 (ZCZ ball B8) AIN5 */ ++ ++ /* P9_37 (ZCZ ball B7) AIN2 */ ++ ++ /* P9_38 (ZCZ ball A7) AIN3 */ ++ ++ /* P9_39 (ZCZ ball B6) AIN0 */ ++ ++ /* P9_40 (ZCZ ball C7) AIN1 */ ++ ++ /* P9_41 (ZCZ ball D14) xdma_event_intr1 (gpio0_20) */ ++ BONE_PIN(P9_41, default, P9_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_41, gpio, P9_41(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_41, gpio_pu, P9_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_41, gpio_pd, P9_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_41, timer, P9_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4)) ++ BONE_PIN(P9_41, pruin, P9_41(PIN_INPUT | MUX_MODE5)) ++ ++ /* P9_41.1 */ ++ /* P9_91 (ZCZ ball D13) mcasp0_axr1 (gpio3_20) */ ++ BONE_PIN(P9_91, default, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_91, gpio, P9_91(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_91, gpio_pu, P9_91(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_91, gpio_pd, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_91, eqep, P9_91(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_91, pruout, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_91, pruin, P9_91(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_42 (ZCZ ball C18) eCAP0_in_PWM0_out (gpio0_7) */ ++ BONE_PIN(P9_42, default, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, gpio, P9_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, gpio_pu, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, gpio_pd, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_42, pwm, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE0)) ++ BONE_PIN(P9_42, uart, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_42, spi_cs, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2)) ++ BONE_PIN(P9_42, pru_ecap_pwm, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3)) ++ BONE_PIN(P9_42, spi_sclk, P9_42(PIN_INPUT_PULLUP | MUX_MODE4)) ++ ++ /* P9_42.1 */ ++ /* P9_92 (ZCZ ball B12) mcasp0_aclkr (gpio3_18) */ ++ BONE_PIN(P9_92, default, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, gpio, P9_92(PIN_OUTPUT | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, gpio_pu, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, gpio_pd, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7)) ++ BONE_PIN(P9_92, eqep, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1)) ++ BONE_PIN(P9_92, pruout, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5)) ++ BONE_PIN(P9_92, pruin, P9_92(PIN_INPUT | MUX_MODE6)) ++ ++ /* P9_43 GND */ ++ ++ /* P9_44 GND */ ++ ++ /* P9_45 GND */ ++ ++ /* P9_46 GND */ ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ clock-frequency = <100000>; ++ symlink = "bone/i2c/1"; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ clock-frequency = <100000>; ++ symlink = "bone/i2c/2"; ++}; ++ ++&uart1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/1"; ++}; ++ ++&uart2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/2"; ++}; ++ ++&uart3 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/3"; ++}; ++ ++&uart4 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/4"; ++}; ++ ++&uart5 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/uart/5"; ++}; ++ ++&dcan0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/can/0"; ++}; ++ ++&dcan1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/can/1"; ++}; ++ ++&eqep0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/eqep/0"; ++}; ++ ++&eqep1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/eqep/1"; ++}; ++ ++&eqep2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ symlink = "bone/eqep/2"; ++}; ++ ++&epwmss0 { ++ status = "okay"; ++}; ++ ++&epwmss1 { ++ status = "okay"; ++}; ++ ++&epwmss2 { ++ status = "okay"; ++}; ++ ++&ehrpwm0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ehrpwm1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ehrpwm2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ecap0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ecap1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&ecap2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++}; ++ ++&spi0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/0.0"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/0.1"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++}; ++ ++&spi1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/1.0"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/1.1"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++}; ++ ++/**********************************************************************/ ++/* Pin Multiplex Helpers */ ++/* */ ++/* These provide userspace runtime pin configuration for the */ ++/* BeagleBone cape expansion headers */ ++/**********************************************************************/ ++ ++&ocp { ++ /************************/ ++ /* P8 Header */ ++ /************************/ ++ ++ /* P8_01 GND */ ++ ++ /* P8_02 GND */ ++ ++ ++ /* P8_03 (ZCZ ball R9) emmc */ ++ P8_03_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_03_default_pin>; ++ pinctrl-1 = <&P8_03_gpio_pin>; ++ pinctrl-2 = <&P8_03_gpio_pu_pin>; ++ pinctrl-3 = <&P8_03_gpio_pd_pin>; ++ }; ++ ++ /* P8_04 (ZCZ ball T9) emmc */ ++ P8_04_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_04_default_pin>; ++ pinctrl-1 = <&P8_04_gpio_pin>; ++ pinctrl-2 = <&P8_04_gpio_pu_pin>; ++ pinctrl-3 = <&P8_04_gpio_pd_pin>; ++ }; ++ ++ /* P8_05 (ZCZ ball R8) emmc */ ++ P8_05_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_05_default_pin>; ++ pinctrl-1 = <&P8_05_gpio_pin>; ++ pinctrl-2 = <&P8_05_gpio_pu_pin>; ++ pinctrl-3 = <&P8_05_gpio_pd_pin>; ++ }; ++ ++ /* P8_06 (ZCZ ball T8) emmc */ ++ P8_06_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_06_default_pin>; ++ pinctrl-1 = <&P8_06_gpio_pin>; ++ pinctrl-2 = <&P8_06_gpio_pu_pin>; ++ pinctrl-3 = <&P8_06_gpio_pd_pin>; ++ }; ++ ++ /* P8_07 (ZCZ ball R7) */ ++ P8_07_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_07_default_pin>; ++ pinctrl-1 = <&P8_07_gpio_pin>; ++ pinctrl-2 = <&P8_07_gpio_pu_pin>; ++ pinctrl-3 = <&P8_07_gpio_pd_pin>; ++ pinctrl-4 = <&P8_07_timer_pin>; ++ }; ++ ++ /* P8_08 (ZCZ ball T7) */ ++ P8_08_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_08_default_pin>; ++ pinctrl-1 = <&P8_08_gpio_pin>; ++ pinctrl-2 = <&P8_08_gpio_pu_pin>; ++ pinctrl-3 = <&P8_08_gpio_pd_pin>; ++ pinctrl-4 = <&P8_08_timer_pin>; ++ }; ++ ++ /* P8_09 (ZCZ ball T6) */ ++ P8_09_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_09_default_pin>; ++ pinctrl-1 = <&P8_09_gpio_pin>; ++ pinctrl-2 = <&P8_09_gpio_pu_pin>; ++ pinctrl-3 = <&P8_09_gpio_pd_pin>; ++ pinctrl-4 = <&P8_09_timer_pin>; ++ }; ++ ++ /* P8_10 (ZCZ ball U6) */ ++ P8_10_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer"; ++ pinctrl-0 = <&P8_10_default_pin>; ++ pinctrl-1 = <&P8_10_gpio_pin>; ++ pinctrl-2 = <&P8_10_gpio_pu_pin>; ++ pinctrl-3 = <&P8_10_gpio_pd_pin>; ++ pinctrl-4 = <&P8_10_timer_pin>; ++ }; ++ ++ /* P8_11 (ZCZ ball R12) */ ++ P8_11_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout"; ++ pinctrl-0 = <&P8_11_default_pin>; ++ pinctrl-1 = <&P8_11_gpio_pin>; ++ pinctrl-2 = <&P8_11_gpio_pu_pin>; ++ pinctrl-3 = <&P8_11_gpio_pd_pin>; ++ pinctrl-4 = <&P8_11_eqep_pin>; ++ pinctrl-5 = <&P8_11_pruout_pin>; ++ }; ++ ++ /* P8_12 (ZCZ ball T12) */ ++ P8_12_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout"; ++ pinctrl-0 = <&P8_12_default_pin>; ++ pinctrl-1 = <&P8_12_gpio_pin>; ++ pinctrl-2 = <&P8_12_gpio_pu_pin>; ++ pinctrl-3 = <&P8_12_gpio_pd_pin>; ++ pinctrl-4 = <&P8_12_eqep_pin>; ++ pinctrl-5 = <&P8_12_pruout_pin>; ++ }; ++ ++ /* P8_13 (ZCZ ball T10) */ ++ P8_13_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_13_default_pin>; ++ pinctrl-1 = <&P8_13_gpio_pin>; ++ pinctrl-2 = <&P8_13_gpio_pu_pin>; ++ pinctrl-3 = <&P8_13_gpio_pd_pin>; ++ pinctrl-4 = <&P8_13_pwm_pin>; ++ }; ++ ++ /* P8_14 (ZCZ ball T11) wl1835: wl_en */ ++ ++ /* P8_15 (ZCZ ball U13) */ ++ P8_15_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pru_ecap_pwm", "pruin"; ++ pinctrl-0 = <&P8_15_default_pin>; ++ pinctrl-1 = <&P8_15_gpio_pin>; ++ pinctrl-2 = <&P8_15_gpio_pu_pin>; ++ pinctrl-3 = <&P8_15_gpio_pd_pin>; ++ pinctrl-4 = <&P8_15_eqep_pin>; ++ pinctrl-5 = <&P8_15_pru_ecap_pwm_pin>; ++ pinctrl-6 = <&P8_15_pruin_pin>; ++ }; ++ ++ /* P8_16 (ZCZ ball V13) */ ++ P8_16_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruin"; ++ pinctrl-0 = <&P8_16_default_pin>; ++ pinctrl-1 = <&P8_16_gpio_pin>; ++ pinctrl-2 = <&P8_16_gpio_pu_pin>; ++ pinctrl-3 = <&P8_16_gpio_pd_pin>; ++ pinctrl-4 = <&P8_16_eqep_pin>; ++ pinctrl-5 = <&P8_16_pruin_pin>; ++ }; ++ ++ /* P8_17 (ZCZ ball U12) wl1835: wl_irq */ ++ ++ /* P8_18 (ZCZ ball V12) */ ++ P8_18_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_18_default_pin>; ++ pinctrl-1 = <&P8_18_gpio_pin>; ++ pinctrl-2 = <&P8_18_gpio_pu_pin>; ++ pinctrl-3 = <&P8_18_gpio_pd_pin>; ++ }; ++ ++ /* P8_19 (ZCZ ball U10) */ ++ P8_19_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_19_default_pin>; ++ pinctrl-1 = <&P8_19_gpio_pin>; ++ pinctrl-2 = <&P8_19_gpio_pu_pin>; ++ pinctrl-3 = <&P8_19_gpio_pd_pin>; ++ pinctrl-4 = <&P8_19_pwm_pin>; ++ }; ++ ++ /* P8_20 (ZCZ ball V9) emmc */ ++ P8_20_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_20_default_pin>; ++ pinctrl-1 = <&P8_20_gpio_pin>; ++ pinctrl-2 = <&P8_20_gpio_pu_pin>; ++ pinctrl-3 = <&P8_20_gpio_pd_pin>; ++ pinctrl-4 = <&P8_20_pruout_pin>; ++ pinctrl-5 = <&P8_20_pruin_pin>; ++ }; ++ ++ /* P8_21 (ZCZ ball U9) emmc */ ++ P8_21_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_21_default_pin>; ++ pinctrl-1 = <&P8_21_gpio_pin>; ++ pinctrl-2 = <&P8_21_gpio_pu_pin>; ++ pinctrl-3 = <&P8_21_gpio_pd_pin>; ++ pinctrl-4 = <&P8_21_pruout_pin>; ++ pinctrl-5 = <&P8_21_pruin_pin>; ++ }; ++ ++ /* P8_22 (ZCZ ball V8) emmc */ ++ P8_22_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_22_default_pin>; ++ pinctrl-1 = <&P8_22_gpio_pin>; ++ pinctrl-2 = <&P8_22_gpio_pu_pin>; ++ pinctrl-3 = <&P8_22_gpio_pd_pin>; ++ }; ++ ++ /* P8_23 (ZCZ ball U8) emmc */ ++ P8_23_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_23_default_pin>; ++ pinctrl-1 = <&P8_23_gpio_pin>; ++ pinctrl-2 = <&P8_23_gpio_pu_pin>; ++ pinctrl-3 = <&P8_23_gpio_pd_pin>; ++ }; ++ ++ /* P8_24 (ZCZ ball V7) emmc */ ++ P8_24_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_24_default_pin>; ++ pinctrl-1 = <&P8_24_gpio_pin>; ++ pinctrl-2 = <&P8_24_gpio_pu_pin>; ++ pinctrl-3 = <&P8_24_gpio_pd_pin>; ++ }; ++ ++ /* P8_25 (ZCZ ball U7) emmc */ ++ P8_25_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P8_25_default_pin>; ++ pinctrl-1 = <&P8_25_gpio_pin>; ++ pinctrl-2 = <&P8_25_gpio_pu_pin>; ++ pinctrl-3 = <&P8_25_gpio_pd_pin>; ++ }; ++ ++ /* P8_26 (ZCZ ball V6) gpio-hog wl1835 */ ++ ++ /* P8_27 (ZCZ ball U5) hdmi */ ++ P8_27_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_27_default_pin>; ++ pinctrl-1 = <&P8_27_gpio_pin>; ++ pinctrl-2 = <&P8_27_gpio_pu_pin>; ++ pinctrl-3 = <&P8_27_gpio_pd_pin>; ++ pinctrl-4 = <&P8_27_pruout_pin>; ++ pinctrl-5 = <&P8_27_pruin_pin>; ++ }; ++ ++ /* P8_28 (ZCZ ball V5) hdmi */ ++ P8_28_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_28_default_pin>; ++ pinctrl-1 = <&P8_28_gpio_pin>; ++ pinctrl-2 = <&P8_28_gpio_pu_pin>; ++ pinctrl-3 = <&P8_28_gpio_pd_pin>; ++ pinctrl-4 = <&P8_28_pruout_pin>; ++ pinctrl-5 = <&P8_28_pruin_pin>; ++ }; ++ ++ /* P8_29 (ZCZ ball R5) hdmi */ ++ P8_29_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_29_default_pin>; ++ pinctrl-1 = <&P8_29_gpio_pin>; ++ pinctrl-2 = <&P8_29_gpio_pu_pin>; ++ pinctrl-3 = <&P8_29_gpio_pd_pin>; ++ pinctrl-4 = <&P8_29_pruout_pin>; ++ pinctrl-5 = <&P8_29_pruin_pin>; ++ }; ++ ++ /* P8_30 (ZCZ ball R6) hdmi */ ++ P8_30_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin"; ++ pinctrl-0 = <&P8_30_default_pin>; ++ pinctrl-1 = <&P8_30_gpio_pin>; ++ pinctrl-2 = <&P8_30_gpio_pu_pin>; ++ pinctrl-3 = <&P8_30_gpio_pd_pin>; ++ pinctrl-4 = <&P8_30_pruout_pin>; ++ pinctrl-5 = <&P8_30_pruin_pin>; ++ }; ++ ++ /* P8_31 (ZCZ ball V4) hdmi */ ++ P8_31_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "eqep"; ++ pinctrl-0 = <&P8_31_default_pin>; ++ pinctrl-1 = <&P8_31_gpio_pin>; ++ pinctrl-2 = <&P8_31_gpio_pu_pin>; ++ pinctrl-3 = <&P8_31_gpio_pd_pin>; ++ pinctrl-4 = <&P8_31_uart_pin>; ++ pinctrl-5 = <&P8_31_eqep_pin>; ++ }; ++ ++ /* P8_32 (ZCZ ball T5) hdmi */ ++ P8_32_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep"; ++ pinctrl-0 = <&P8_32_default_pin>; ++ pinctrl-1 = <&P8_32_gpio_pin>; ++ pinctrl-2 = <&P8_32_gpio_pu_pin>; ++ pinctrl-3 = <&P8_32_gpio_pd_pin>; ++ pinctrl-4 = <&P8_32_eqep_pin>; ++ }; ++ ++ /* P8_33 (ZCZ ball V3) hdmi */ ++ P8_33_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep"; ++ pinctrl-0 = <&P8_33_default_pin>; ++ pinctrl-1 = <&P8_33_gpio_pin>; ++ pinctrl-2 = <&P8_33_gpio_pu_pin>; ++ pinctrl-3 = <&P8_33_gpio_pd_pin>; ++ pinctrl-4 = <&P8_33_eqep_pin>; ++ }; ++ ++ /* P8_34 (ZCZ ball U4) hdmi */ ++ P8_34_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_34_default_pin>; ++ pinctrl-1 = <&P8_34_gpio_pin>; ++ pinctrl-2 = <&P8_34_gpio_pu_pin>; ++ pinctrl-3 = <&P8_34_gpio_pd_pin>; ++ pinctrl-4 = <&P8_34_pwm_pin>; ++ }; ++ ++ /* P8_35 (ZCZ ball V2) hdmi */ ++ P8_35_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep"; ++ pinctrl-0 = <&P8_35_default_pin>; ++ pinctrl-1 = <&P8_35_gpio_pin>; ++ pinctrl-2 = <&P8_35_gpio_pu_pin>; ++ pinctrl-3 = <&P8_35_gpio_pd_pin>; ++ pinctrl-4 = <&P8_35_eqep_pin>; ++ }; ++ ++ /* P8_36 (ZCZ ball U3) hdmi */ ++ P8_36_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P8_36_default_pin>; ++ pinctrl-1 = <&P8_36_gpio_pin>; ++ pinctrl-2 = <&P8_36_gpio_pu_pin>; ++ pinctrl-3 = <&P8_36_gpio_pd_pin>; ++ pinctrl-4 = <&P8_36_pwm_pin>; ++ }; ++ ++ /* P8_37 (ZCZ ball U1) hdmi */ ++ P8_37_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "pwm"; ++ pinctrl-0 = <&P8_37_default_pin>; ++ pinctrl-1 = <&P8_37_gpio_pin>; ++ pinctrl-2 = <&P8_37_gpio_pu_pin>; ++ pinctrl-3 = <&P8_37_gpio_pd_pin>; ++ pinctrl-4 = <&P8_37_uart_pin>; ++ pinctrl-5 = <&P8_37_pwm_pin>; ++ }; ++ ++ /* P8_38 (ZCZ ball U2) hdmi */ ++ P8_38_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "pwm"; ++ pinctrl-0 = <&P8_38_default_pin>; ++ pinctrl-1 = <&P8_38_gpio_pin>; ++ pinctrl-2 = <&P8_38_gpio_pu_pin>; ++ pinctrl-3 = <&P8_38_gpio_pd_pin>; ++ pinctrl-4 = <&P8_38_uart_pin>; ++ pinctrl-5 = <&P8_38_pwm_pin>; ++ }; ++ ++ /* P8_39 (ZCZ ball T3) hdmi */ ++ P8_39_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P8_39_default_pin>; ++ pinctrl-1 = <&P8_39_gpio_pin>; ++ pinctrl-2 = <&P8_39_gpio_pu_pin>; ++ pinctrl-3 = <&P8_39_gpio_pd_pin>; ++ pinctrl-4 = <&P8_39_eqep_pin>; ++ pinctrl-5 = <&P8_39_pruout_pin>; ++ pinctrl-6 = <&P8_39_pruin_pin>; ++ }; ++ ++ /* P8_40 (ZCZ ball T4) hdmi */ ++ P8_40_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P8_40_default_pin>; ++ pinctrl-1 = <&P8_40_gpio_pin>; ++ pinctrl-2 = <&P8_40_gpio_pu_pin>; ++ pinctrl-3 = <&P8_40_gpio_pd_pin>; ++ pinctrl-4 = <&P8_40_eqep_pin>; ++ pinctrl-5 = <&P8_40_pruout_pin>; ++ pinctrl-6 = <&P8_40_pruin_pin>; ++ }; ++ ++ /* P8_41 (ZCZ ball T1) hdmi */ ++ P8_41_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P8_41_default_pin>; ++ pinctrl-1 = <&P8_41_gpio_pin>; ++ pinctrl-2 = <&P8_41_gpio_pu_pin>; ++ pinctrl-3 = <&P8_41_gpio_pd_pin>; ++ pinctrl-4 = <&P8_41_eqep_pin>; ++ pinctrl-5 = <&P8_41_pruout_pin>; ++ pinctrl-6 = <&P8_41_pruin_pin>; ++ }; ++ ++ /* P8_42 (ZCZ ball T2) hdmi */ ++ P8_42_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P8_42_default_pin>; ++ pinctrl-1 = <&P8_42_gpio_pin>; ++ pinctrl-2 = <&P8_42_gpio_pu_pin>; ++ pinctrl-3 = <&P8_42_gpio_pd_pin>; ++ pinctrl-4 = <&P8_42_eqep_pin>; ++ pinctrl-5 = <&P8_42_pruout_pin>; ++ pinctrl-6 = <&P8_42_pruin_pin>; ++ }; ++ ++ /* P8_43 (ZCZ ball R3) hdmi */ ++ P8_43_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P8_43_default_pin>; ++ pinctrl-1 = <&P8_43_gpio_pin>; ++ pinctrl-2 = <&P8_43_gpio_pu_pin>; ++ pinctrl-3 = <&P8_43_gpio_pd_pin>; ++ pinctrl-4 = <&P8_43_pwm_pin>; ++ pinctrl-5 = <&P8_43_pruout_pin>; ++ pinctrl-6 = <&P8_43_pruin_pin>; ++ }; ++ ++ /* P8_44 (ZCZ ball R4) hdmi */ ++ P8_44_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P8_44_default_pin>; ++ pinctrl-1 = <&P8_44_gpio_pin>; ++ pinctrl-2 = <&P8_44_gpio_pu_pin>; ++ pinctrl-3 = <&P8_44_gpio_pd_pin>; ++ pinctrl-4 = <&P8_44_pwm_pin>; ++ pinctrl-5 = <&P8_44_pruout_pin>; ++ pinctrl-6 = <&P8_44_pruin_pin>; ++ }; ++ ++ /* P8_45 (ZCZ ball R1) hdmi */ ++ P8_45_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P8_45_default_pin>; ++ pinctrl-1 = <&P8_45_gpio_pin>; ++ pinctrl-2 = <&P8_45_gpio_pu_pin>; ++ pinctrl-3 = <&P8_45_gpio_pd_pin>; ++ pinctrl-4 = <&P8_45_pwm_pin>; ++ pinctrl-5 = <&P8_45_pruout_pin>; ++ pinctrl-6 = <&P8_45_pruin_pin>; ++ }; ++ ++ /* P8_46 (ZCZ ball R2) hdmi */ ++ P8_46_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P8_46_default_pin>; ++ pinctrl-1 = <&P8_46_gpio_pin>; ++ pinctrl-2 = <&P8_46_gpio_pu_pin>; ++ pinctrl-3 = <&P8_46_gpio_pd_pin>; ++ pinctrl-4 = <&P8_46_pwm_pin>; ++ pinctrl-5 = <&P8_46_pruout_pin>; ++ pinctrl-6 = <&P8_46_pruin_pin>; ++ }; ++ ++ /************************/ ++ /* P9 Header */ ++ /************************/ ++ ++ /* P9_01 GND */ ++ ++ /* P9_02 GND */ ++ ++ /* P9_03 3V3 */ ++ ++ /* P9_04 3V3 */ ++ ++ /* P9_05 VDD_5V */ ++ ++ /* P9_06 VDD_5V */ ++ ++ /* P9_07 SYS_5V */ ++ ++ /* P9_08 SYS_5V */ ++ ++ /* P9_09 PWR_BUT */ ++ ++ /* P9_10 RSTn */ ++ ++ /* P9_11 (ZCZ ball T17) */ ++ P9_11_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; ++ pinctrl-0 = <&P9_11_default_pin>; ++ pinctrl-1 = <&P9_11_gpio_pin>; ++ pinctrl-2 = <&P9_11_gpio_pu_pin>; ++ pinctrl-3 = <&P9_11_gpio_pd_pin>; ++ pinctrl-4 = <&P9_11_uart_pin>; ++ }; ++ ++ /* P9_12 (ZCZ ball U18) */ ++ P9_12_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd"; ++ pinctrl-0 = <&P9_12_default_pin>; ++ pinctrl-1 = <&P9_12_gpio_pin>; ++ pinctrl-2 = <&P9_12_gpio_pu_pin>; ++ pinctrl-3 = <&P9_12_gpio_pd_pin>; ++ }; ++ ++ /* P9_13 (ZCZ ball U17) */ ++ P9_13_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart"; ++ pinctrl-0 = <&P9_13_default_pin>; ++ pinctrl-1 = <&P9_13_gpio_pin>; ++ pinctrl-2 = <&P9_13_gpio_pu_pin>; ++ pinctrl-3 = <&P9_13_gpio_pd_pin>; ++ pinctrl-4 = <&P9_13_uart_pin>; ++ }; ++ ++ /* P9_14 (ZCZ ball U14) */ ++ P9_14_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_14_default_pin>; ++ pinctrl-1 = <&P9_14_gpio_pin>; ++ pinctrl-2 = <&P9_14_gpio_pu_pin>; ++ pinctrl-3 = <&P9_14_gpio_pd_pin>; ++ pinctrl-4 = <&P9_14_pwm_pin>; ++ }; ++ ++ /* P9_15 (ZCZ ball R13) */ ++ P9_15_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_15_default_pin>; ++ pinctrl-1 = <&P9_15_gpio_pin>; ++ pinctrl-2 = <&P9_15_gpio_pu_pin>; ++ pinctrl-3 = <&P9_15_gpio_pd_pin>; ++ pinctrl-4 = <&P9_15_pwm_pin>; ++ }; ++ ++ /* P9_16 (ZCZ ball T14) */ ++ P9_16_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_16_default_pin>; ++ pinctrl-1 = <&P9_16_gpio_pin>; ++ pinctrl-2 = <&P9_16_gpio_pu_pin>; ++ pinctrl-3 = <&P9_16_gpio_pd_pin>; ++ pinctrl-4 = <&P9_16_pwm_pin>; ++ }; ++ ++ /* P9_17 (ZCZ ball A16) */ ++ P9_17_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "i2c", "pwm", "pru_uart"; ++ pinctrl-0 = <&P9_17_default_pin>; ++ pinctrl-1 = <&P9_17_gpio_pin>; ++ pinctrl-2 = <&P9_17_gpio_pu_pin>; ++ pinctrl-3 = <&P9_17_gpio_pd_pin>; ++ pinctrl-4 = <&P9_17_spi_cs_pin>; ++ pinctrl-5 = <&P9_17_i2c_pin>; ++ pinctrl-6 = <&P9_17_pwm_pin>; ++ pinctrl-7 = <&P9_17_pru_uart_pin>; ++ }; ++ ++ /* P9_18 (ZCZ ball B16) */ ++ P9_18_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm", "pru_uart"; ++ pinctrl-0 = <&P9_18_default_pin>; ++ pinctrl-1 = <&P9_18_gpio_pin>; ++ pinctrl-2 = <&P9_18_gpio_pu_pin>; ++ pinctrl-3 = <&P9_18_gpio_pd_pin>; ++ pinctrl-4 = <&P9_18_spi_pin>; ++ pinctrl-5 = <&P9_18_i2c_pin>; ++ pinctrl-6 = <&P9_18_pwm_pin>; ++ pinctrl-7 = <&P9_18_pru_uart_pin>; ++ }; ++ ++ /* P9_19 (ZCZ ball D17) i2c */ ++ P9_19_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart", "timer"; ++ pinctrl-0 = <&P9_19_default_pin>; ++ pinctrl-1 = <&P9_19_gpio_pin>; ++ pinctrl-2 = <&P9_19_gpio_pu_pin>; ++ pinctrl-3 = <&P9_19_gpio_pd_pin>; ++ pinctrl-4 = <&P9_19_spi_cs_pin>; ++ pinctrl-5 = <&P9_19_can_pin>; ++ pinctrl-6 = <&P9_19_i2c_pin>; ++ pinctrl-7 = <&P9_19_pru_uart_pin>; ++ pinctrl-8 = <&P9_19_timer_pin>; ++ }; ++ ++ /* P9_20 (ZCZ ball D18) i2c */ ++ P9_20_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart", "timer"; ++ pinctrl-0 = <&P9_20_default_pin>; ++ pinctrl-1 = <&P9_20_gpio_pin>; ++ pinctrl-2 = <&P9_20_gpio_pu_pin>; ++ pinctrl-3 = <&P9_20_gpio_pd_pin>; ++ pinctrl-4 = <&P9_20_spi_cs_pin>; ++ pinctrl-5 = <&P9_20_can_pin>; ++ pinctrl-6 = <&P9_20_i2c_pin>; ++ pinctrl-7 = <&P9_20_pru_uart_pin>; ++ pinctrl-8 = <&P9_20_timer_pin>; ++ }; ++ ++ /* P9_21 (ZCZ ball B17) */ ++ P9_21_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm", "pru_uart"; ++ pinctrl-0 = <&P9_21_default_pin>; ++ pinctrl-1 = <&P9_21_gpio_pin>; ++ pinctrl-2 = <&P9_21_gpio_pu_pin>; ++ pinctrl-3 = <&P9_21_gpio_pd_pin>; ++ pinctrl-4 = <&P9_21_spi_pin>; ++ pinctrl-5 = <&P9_21_uart_pin>; ++ pinctrl-6 = <&P9_21_i2c_pin>; ++ pinctrl-7 = <&P9_21_pwm_pin>; ++ pinctrl-8 = <&P9_21_pru_uart_pin>; ++ }; ++ ++ /* P9_22 (ZCZ ball A17) */ ++ P9_22_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "uart", "i2c", "pwm", "pru_uart"; ++ pinctrl-0 = <&P9_22_default_pin>; ++ pinctrl-1 = <&P9_22_gpio_pin>; ++ pinctrl-2 = <&P9_22_gpio_pu_pin>; ++ pinctrl-3 = <&P9_22_gpio_pd_pin>; ++ pinctrl-4 = <&P9_22_spi_sclk_pin>; ++ pinctrl-5 = <&P9_22_uart_pin>; ++ pinctrl-6 = <&P9_22_i2c_pin>; ++ pinctrl-7 = <&P9_22_pwm_pin>; ++ pinctrl-8 = <&P9_22_pru_uart_pin>; ++ }; ++ ++ /* P9_23 (ZCZ ball V14) */ ++ P9_23_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm"; ++ pinctrl-0 = <&P9_23_default_pin>; ++ pinctrl-1 = <&P9_23_gpio_pin>; ++ pinctrl-2 = <&P9_23_gpio_pu_pin>; ++ pinctrl-3 = <&P9_23_gpio_pd_pin>; ++ pinctrl-4 = <&P9_23_pwm_pin>; ++ }; ++ ++ /* P9_24 (ZCZ ball D15) */ ++ P9_24_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin"; ++ pinctrl-0 = <&P9_24_default_pin>; ++ pinctrl-1 = <&P9_24_gpio_pin>; ++ pinctrl-2 = <&P9_24_gpio_pu_pin>; ++ pinctrl-3 = <&P9_24_gpio_pd_pin>; ++ pinctrl-4 = <&P9_24_uart_pin>; ++ pinctrl-5 = <&P9_24_can_pin>; ++ pinctrl-6 = <&P9_24_i2c_pin>; ++ pinctrl-7 = <&P9_24_pru_uart_pin>; ++ pinctrl-8 = <&P9_24_pruin_pin>; ++ }; ++ ++ /* P9_25 (ZCZ ball A14) audio */ ++ P9_25_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_25_default_pin>; ++ pinctrl-1 = <&P9_25_gpio_pin>; ++ pinctrl-2 = <&P9_25_gpio_pu_pin>; ++ pinctrl-3 = <&P9_25_gpio_pd_pin>; ++ pinctrl-4 = <&P9_25_eqep_pin>; ++ pinctrl-5 = <&P9_25_pruout_pin>; ++ pinctrl-6 = <&P9_25_pruin_pin>; ++ }; ++ ++ /* P9_26 (ZCZ ball D16) */ ++ P9_26_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin"; ++ pinctrl-0 = <&P9_26_default_pin>; ++ pinctrl-1 = <&P9_26_gpio_pin>; ++ pinctrl-2 = <&P9_26_gpio_pu_pin>; ++ pinctrl-3 = <&P9_26_gpio_pd_pin>; ++ pinctrl-4 = <&P9_26_uart_pin>; ++ pinctrl-5 = <&P9_26_can_pin>; ++ pinctrl-6 = <&P9_26_i2c_pin>; ++ pinctrl-7 = <&P9_26_pru_uart_pin>; ++ pinctrl-8 = <&P9_26_pruin_pin>; ++ }; ++ ++ /* P9_27 (ZCZ ball C13) */ ++ P9_27_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_27_default_pin>; ++ pinctrl-1 = <&P9_27_gpio_pin>; ++ pinctrl-2 = <&P9_27_gpio_pu_pin>; ++ pinctrl-3 = <&P9_27_gpio_pd_pin>; ++ pinctrl-4 = <&P9_27_eqep_pin>; ++ pinctrl-5 = <&P9_27_pruout_pin>; ++ pinctrl-6 = <&P9_27_pruin_pin>; ++ }; ++ ++ /* P9_28 (ZCZ ball C12) audio */ ++ P9_28_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "pwm", "pwm2", "pruout", "pruin"; ++ pinctrl-0 = <&P9_28_default_pin>; ++ pinctrl-1 = <&P9_28_gpio_pin>; ++ pinctrl-2 = <&P9_28_gpio_pu_pin>; ++ pinctrl-3 = <&P9_28_gpio_pd_pin>; ++ pinctrl-4 = <&P9_28_spi_cs_pin>; ++ pinctrl-5 = <&P9_28_pwm_pin>; ++ pinctrl-6 = <&P9_28_pwm2_pin>; ++ pinctrl-7 = <&P9_28_pruout_pin>; ++ pinctrl-8 = <&P9_28_pruin_pin>; ++ }; ++ ++ /* P9_29 (ZCZ ball B13) audio */ ++ P9_29_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P9_29_default_pin>; ++ pinctrl-1 = <&P9_29_gpio_pin>; ++ pinctrl-2 = <&P9_29_gpio_pu_pin>; ++ pinctrl-3 = <&P9_29_gpio_pd_pin>; ++ pinctrl-4 = <&P9_29_spi_pin>; ++ pinctrl-5 = <&P9_29_pwm_pin>; ++ pinctrl-6 = <&P9_29_pruout_pin>; ++ pinctrl-7 = <&P9_29_pruin_pin>; ++ }; ++ ++ /* P9_30 (ZCZ ball D12) gpio-hog wl1835 */ ++ ++ /* P9_31 (ZCZ ball A13) audio */ ++ P9_31_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "pwm", "pruout", "pruin"; ++ pinctrl-0 = <&P9_31_default_pin>; ++ pinctrl-1 = <&P9_31_gpio_pin>; ++ pinctrl-2 = <&P9_31_gpio_pu_pin>; ++ pinctrl-3 = <&P9_31_gpio_pd_pin>; ++ pinctrl-4 = <&P9_31_spi_sclk_pin>; ++ pinctrl-5 = <&P9_31_pwm_pin>; ++ pinctrl-6 = <&P9_31_pruout_pin>; ++ pinctrl-7 = <&P9_31_pruin_pin>; ++ }; ++ ++ /* P9_32 VADC */ ++ ++ /* P9_33 (ZCZ ball C8) AIN4 */ ++ ++ /* P9_34 AGND */ ++ ++ /* P9_35 (ZCZ ball A8) AIN6 */ ++ ++ /* P9_36 (ZCZ ball B8) AIN5 */ ++ ++ /* P9_37 (ZCZ ball B7) AIN2 */ ++ ++ /* P9_38 (ZCZ ball A7) AIN3 */ ++ ++ /* P9_39 (ZCZ ball B6) AIN0 */ ++ ++ /* P9_40 (ZCZ ball C7) AIN1 */ ++ ++ /* P9_41 (ZCZ ball D14) */ ++ P9_41_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer", "pruin"; ++ pinctrl-0 = <&P9_41_default_pin>; ++ pinctrl-1 = <&P9_41_gpio_pin>; ++ pinctrl-2 = <&P9_41_gpio_pu_pin>; ++ pinctrl-3 = <&P9_41_gpio_pd_pin>; ++ pinctrl-4 = <&P9_41_timer_pin>; ++ pinctrl-5 = <&P9_41_pruin_pin>; ++ }; ++ ++ /* P9_41.1 */ ++ /* P9_91 (ZCZ ball D13) */ ++ P9_91_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_91_default_pin>; ++ pinctrl-1 = <&P9_91_gpio_pin>; ++ pinctrl-2 = <&P9_91_gpio_pu_pin>; ++ pinctrl-3 = <&P9_91_gpio_pd_pin>; ++ pinctrl-4 = <&P9_91_eqep_pin>; ++ pinctrl-5 = <&P9_91_pruout_pin>; ++ pinctrl-6 = <&P9_91_pruin_pin>; ++ }; ++ ++ /* P9_42 (ZCZ ball C18) */ ++ P9_42_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "spi_sclk", "uart", "pwm", "pru_ecap_pwm"; ++ pinctrl-0 = <&P9_42_default_pin>; ++ pinctrl-1 = <&P9_42_gpio_pin>; ++ pinctrl-2 = <&P9_42_gpio_pu_pin>; ++ pinctrl-3 = <&P9_42_gpio_pd_pin>; ++ pinctrl-4 = <&P9_42_spi_cs_pin>; ++ pinctrl-5 = <&P9_42_spi_sclk_pin>; ++ pinctrl-6 = <&P9_42_uart_pin>; ++ pinctrl-7 = <&P9_42_pwm_pin>; ++ pinctrl-8 = <&P9_42_pru_ecap_pwm_pin>; ++ }; ++ ++ /* P9_42.1 */ ++ /* P9_92 (ZCZ ball B12) */ ++ P9_92_pinmux { ++ compatible = "bone-pinmux-helper"; ++ status = "okay"; ++ pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin"; ++ pinctrl-0 = <&P9_92_default_pin>; ++ pinctrl-1 = <&P9_92_gpio_pin>; ++ pinctrl-2 = <&P9_92_gpio_pu_pin>; ++ pinctrl-3 = <&P9_92_gpio_pd_pin>; ++ pinctrl-4 = <&P9_92_eqep_pin>; ++ pinctrl-5 = <&P9_92_pruout_pin>; ++ pinctrl-6 = <&P9_92_pruin_pin>; ++ }; ++ ++ /* P9_43 GND */ ++ ++ /* P9_44 GND */ ++ ++ /* P9_45 GND */ ++ ++ /* P9_46 GND */ ++ ++ cape-universal { ++ compatible = "gpio-of-helper"; ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <>; ++ ++ P8_03 { ++ gpio-name = "P8_03"; ++ gpio = <&gpio1 6 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_04 { ++ gpio-name = "P8_04"; ++ gpio = <&gpio1 7 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_05 { ++ gpio-name = "P8_05"; ++ gpio = <&gpio1 2 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_06 { ++ gpio-name = "P8_06"; ++ gpio = <&gpio1 3 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_07 { ++ gpio-name = "P8_07"; ++ gpio = <&gpio2 2 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_08 { ++ gpio-name = "P8_08"; ++ gpio = <&gpio2 3 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_09 { ++ gpio-name = "P8_09"; ++ gpio = <&gpio2 5 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_10 { ++ gpio-name = "P8_10"; ++ gpio = <&gpio2 4 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_11 { ++ gpio-name = "P8_11"; ++ gpio = <&gpio1 13 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_12 { ++ gpio-name = "P8_12"; ++ gpio = <&gpio1 12 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_13 { ++ gpio-name = "P8_13"; ++ gpio = <&gpio0 23 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_15 { ++ gpio-name = "P8_15"; ++ gpio = <&gpio1 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_16 { ++ gpio-name = "P8_16"; ++ gpio = <&gpio1 14 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_18 { ++ gpio-name = "P8_18"; ++ gpio = <&gpio2 1 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_19 { ++ gpio-name = "P8_19"; ++ gpio = <&gpio0 22 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_20 { ++ gpio-name = "P8_20"; ++ gpio = <&gpio1 31 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_21 { ++ gpio-name = "P8_21"; ++ gpio = <&gpio1 30 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_22 { ++ gpio-name = "P8_22"; ++ gpio = <&gpio1 5 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_23 { ++ gpio-name = "P8_23"; ++ gpio = <&gpio1 4 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_24 { ++ gpio-name = "P8_24"; ++ gpio = <&gpio1 1 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_25 { ++ gpio-name = "P8_25"; ++ gpio = <&gpio1 0 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_27 { ++ gpio-name = "P8_27"; ++ gpio = <&gpio2 22 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_28 { ++ gpio-name = "P8_28"; ++ gpio = <&gpio2 24 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_29 { ++ gpio-name = "P8_29"; ++ gpio = <&gpio2 23 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_30 { ++ gpio-name = "P8_30"; ++ gpio = <&gpio2 25 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_31 { ++ gpio-name = "P8_31"; ++ gpio = <&gpio0 10 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_32 { ++ gpio-name = "P8_32"; ++ gpio = <&gpio0 11 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_33 { ++ gpio-name = "P8_33"; ++ gpio = <&gpio0 9 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_34 { ++ gpio-name = "P8_34"; ++ gpio = <&gpio2 17 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_35 { ++ gpio-name = "P8_35"; ++ gpio = <&gpio0 8 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_36 { ++ gpio-name = "P8_36"; ++ gpio = <&gpio2 16 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_37 { ++ gpio-name = "P8_37"; ++ gpio = <&gpio2 14 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_38 { ++ gpio-name = "P8_38"; ++ gpio = <&gpio2 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_39 { ++ gpio-name = "P8_39"; ++ gpio = <&gpio2 12 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_40 { ++ gpio-name = "P8_40"; ++ gpio = <&gpio2 13 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_41 { ++ gpio-name = "P8_41"; ++ gpio = <&gpio2 10 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_42 { ++ gpio-name = "P8_42"; ++ gpio = <&gpio2 11 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_43 { ++ gpio-name = "P8_43"; ++ gpio = <&gpio2 8 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_44 { ++ gpio-name = "P8_44"; ++ gpio = <&gpio2 9 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_45 { ++ gpio-name = "P8_45"; ++ gpio = <&gpio2 6 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P8_46 { ++ gpio-name = "P8_46"; ++ gpio = <&gpio2 7 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_11 { ++ gpio-name = "P9_11"; ++ gpio = <&gpio0 30 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_12 { ++ gpio-name = "P9_12"; ++ gpio = <&gpio1 28 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_13 { ++ gpio-name = "P9_13"; ++ gpio = <&gpio0 31 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_14 { ++ gpio-name = "P9_14"; ++ gpio = <&gpio1 18 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_15 { ++ gpio-name = "P9_15"; ++ gpio = <&gpio1 16 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_16 { ++ gpio-name = "P9_16"; ++ gpio = <&gpio1 19 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_17 { ++ gpio-name = "P9_17"; ++ gpio = <&gpio0 5 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_18 { ++ gpio-name = "P9_18"; ++ gpio = <&gpio0 4 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_19 { ++ gpio-name = "P9_19"; ++ gpio = <&gpio0 13 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_20 { ++ gpio-name = "P9_20"; ++ gpio = <&gpio0 12 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_21 { ++ gpio-name = "P9_21"; ++ gpio = <&gpio0 3 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_22 { ++ gpio-name = "P9_22"; ++ gpio = <&gpio0 2 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_23 { ++ gpio-name = "P9_23"; ++ gpio = <&gpio1 17 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_24 { ++ gpio-name = "P9_24"; ++ gpio = <&gpio0 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_25 { ++ gpio-name = "P9_25"; ++ gpio = <&gpio3 21 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_26 { ++ gpio-name = "P9_26"; ++ gpio = <&gpio0 14 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_27 { ++ gpio-name = "P9_27"; ++ gpio = <&gpio3 19 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_28 { ++ gpio-name = "P9_28"; ++ gpio = <&gpio3 17 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_29 { ++ gpio-name = "P9_29"; ++ gpio = <&gpio3 15 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_31 { ++ gpio-name = "P9_31"; ++ gpio = <&gpio3 14 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_41 { ++ gpio-name = "P9_41"; ++ gpio = <&gpio0 20 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_91 { ++ gpio-name = "P9_91"; ++ gpio = <&gpio3 20 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_42 { ++ gpio-name = "P9_42"; ++ gpio = <&gpio0 7 0>; ++ input; ++ dir-changeable; ++ }; ++ ++ P9_92 { ++ gpio-name = "P9_92"; ++ gpio = <&gpio3 18 0>; ++ input; ++ dir-changeable; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless.dts b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -13,6 +13,12 @@ + model = "TI AM335x BeagleBone Green Wireless"; + compatible = "ti,am335x-bone-green-wireless", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; + ++ chosen { ++ base_dtb = "am335x-bonegreen-wireless.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ wl1835_bt = "S3-texas-300000"; ++ }; ++ + wlan_en_reg: fixedregulator@2 { + compatible = "regulator-fixed"; + regulator-name = "wlan-en-regulator"; +@@ -24,9 +30,60 @@ + gpio = <&gpio0 26 0>; + enable-active-high; + }; ++ ++ leds { ++ pinctrl-names = "default"; ++ //pinctrl-0 = <&user_leds_s0>; ++ pinctrl-0 = <&user_leds_s0 &bt_pins>; ++ ++ compatible = "gpio-leds"; ++ ++ led2 { ++ label = "beaglebone:green:usr0"; ++ gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ default-state = "off"; ++ }; ++ ++ led3 { ++ label = "beaglebone:green:usr1"; ++ gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc0"; ++ default-state = "off"; ++ }; ++ ++ led4 { ++ label = "beaglebone:green:usr2"; ++ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "cpu0"; ++ default-state = "off"; ++ }; ++ ++ led5 { ++ label = "beaglebone:green:usr3"; ++ gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc1"; ++ default-state = "off"; ++ }; ++ ++ wl18xx_bt_en: led7 { ++ label = "wl18xx_bt_en"; ++ gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; + }; + + &am33xx_pinmux { ++ user_leds_s0: user-leds-s0-pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a6.gpio1_22 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a7.gpio1_23 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a8.gpio1_24 */ ++ >; ++ }; ++ + bt_pins: bt-pins { + pinctrl-single,pins = < + AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_ad12.gpio1_28 BT_EN */ +@@ -63,6 +120,9 @@ + }; + + &mac_sw { ++ /delete-property/pinctrl-names; ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-1; + status = "disabled"; + }; + +@@ -91,13 +151,14 @@ + + &uart3 { + pinctrl-names = "default"; +- pinctrl-0 = <&uart3_pins &bt_pins>; ++ pinctrl-0 = <&uart3_pins>; ++ //pinctrl-0 = <&uart3_pins &bt_pins>; + status = "okay"; + +- bluetooth { +- compatible = "ti,wl1835-st"; +- enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; +- }; ++ //bluetooth { ++ // compatible = "ti,wl1835-st"; ++ // enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; ++ //}; + }; + + &gpio1 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless-uboot-univ.dts b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless-uboot-univ.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless-uboot-univ.dts 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-bonegreen-wireless-uboot-univ.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,56 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++/dts-v1/; ++ ++#include "am33xx.dtsi" ++#include "am335x-bone-common.dtsi" ++#include "am335x-bonegreen-wireless-common-univ.dtsi" ++#include ++ ++/ { ++ model = "TI AM335x BeagleBone Green Wireless"; ++ compatible = "ti,am335x-bone-green-wireless", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-bonegreen-wireless-uboot-univ.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; ++}; ++ ++&ldo3_reg { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++}; ++ ++&mmc1 { ++ vmmc-supply = <&vmmcsd_fixed>; ++}; ++ ++&gpio1 { ++ ls-buf-en-hog { ++ gpio-hog; ++ gpios = <29 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LS_BUF_EN"; ++ }; ++}; ++ ++/* BT_AUD_OUT from wl1835 has to be pulled low when WL_EN is activated.*/ ++/* in case it isn't, wilink8 ends up in one of the test modes that */ ++/* intruces various issues (elp wkaeup timeouts etc.) */ ++/* On the BBGW this pin is routed through the level shifter (U21) that */ ++/* introduces a pullup on the line and wilink8 ends up in a bad state. */ ++/* use a gpio hog to force this pin low. An alternative may be adding */ ++/* an external pulldown on U21 pin 4. */ ++ ++&gpio3 { ++ bt-aud-in-hog { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "MCASP0_AHCLKR"; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-osd3358-sm-red.dts b/arch/arm/boot/dts/ti/omap/am335x-osd3358-sm-red.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-osd3358-sm-red.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-osd3358-sm-red.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -10,13 +10,16 @@ + + #include "am33xx.dtsi" + #include "am335x-osd335x-common.dtsi" +-#include +- +-#include ++#include "am335x-boneblack-hdmi.dtsi" + + / { + model = "Octavo Systems OSD3358-SM-RED"; + compatible = "oct,osd3358-sm-refdesign", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-osd3358-sm-red.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; + + &ldo3_reg { +@@ -33,48 +36,7 @@ + status = "okay"; + }; + +-&lcdc { +- status = "okay"; +- +- /* If you want to get 24 bit RGB and 16 BGR mode instead of +- * current 16 bit RGB and 24 BGR modes, set the propety +- * below to "crossed" and uncomment the video-ports -property +- * in tda19988 node. +- * AM335x errata for wiring: +- * https://www.ti.com/lit/er/sprz360i/sprz360i.pdf +- */ +- +- blue-and-red-wiring = "straight"; +- +- port { +- lcdc_0: endpoint { +- remote-endpoint = <&hdmi_0>; +- }; +- }; +-}; +- + &i2c0 { +- tda19988: hdmi-encoder@70 { +- compatible = "nxp,tda998x"; +- reg = <0x70>; +- +- pinctrl-names = "default", "off"; +- pinctrl-0 = <&nxp_hdmi_bonelt_pins>; +- pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; +- +- /* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */ +- /* video-ports = <0x234501>; */ +- +- #sound-dai-cells = <0>; +- audio-ports = < TDA998x_I2S 0x03>; +- +- port { +- hdmi_0: endpoint { +- remote-endpoint = <&lcdc_0>; +- }; +- }; +- }; +- + mpu9250: imu@68 { + compatible = "invensense,mpu6050"; + reg = <0x68>; +@@ -101,51 +63,7 @@ + }; + }; + +-&mcasp0 { +- #sound-dai-cells = <0>; +- pinctrl-names = "default"; +- pinctrl-0 = <&mcasp0_pins>; +- status = "okay"; +- op-mode = <0>; /* MCASP_IIS_MODE */ +- tdm-slots = <2>; +- serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ +- 0 0 1 0 +- >; +- tx-num-evt = <32>; +- rx-num-evt = <32>; +-}; +- + / { +- clk_mcasp0_fixed: clk-mcasp0-fixed { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <24576000>; +- }; +- +- clk_mcasp0: clk-mcasp0 { +- #clock-cells = <0>; +- compatible = "gpio-gate-clock"; +- clocks = <&clk_mcasp0_fixed>; +- enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */ +- }; +- +- sound { +- compatible = "simple-audio-card"; +- simple-audio-card,name = "TI BeagleBone Black"; +- simple-audio-card,format = "i2s"; +- simple-audio-card,bitclock-master = <&dailink0_master>; +- simple-audio-card,frame-master = <&dailink0_master>; +- +- dailink0_master: simple-audio-card,cpu { +- sound-dai = <&mcasp0>; +- clocks = <&clk_mcasp0>; +- }; +- +- simple-audio-card,codec { +- sound-dai = <&tda19988>; +- }; +- }; +- + chosen { + stdout-path = &uart0; + }; +@@ -194,51 +112,6 @@ + }; + + &am33xx_pinmux { +- pinctrl-names = "default"; +- pinctrl-0 = <&clkout2_pin>; +- +- nxp_hdmi_bonelt_pins: nxp-hdmi-bonelt-pins { +- pinctrl-single,pins = < +- AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0) +- >; +- }; +- +- nxp_hdmi_bonelt_off_pins: nxp-hdmi-bonelt-off-pins { +- pinctrl-single,pins = < +- AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3) +- >; +- }; +- +- mcasp0_pins: mcasp0-pins { +- pinctrl-single,pins = < +- AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/ +- AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLUP, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0) +- AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.GPIO1_27 */ +- >; +- }; +- + flash_enable: flash-enable-pins { + pinctrl-single,pins = < + AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* rmii1_ref_clk.gpio0_29 */ +@@ -280,12 +153,6 @@ + >; + }; + +- clkout2_pin: pinmux-clkout2-pins { +- pinctrl-single,pins = < +- AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* xdma_event_intr1.clkout2 */ +- >; +- }; +- + cpsw_default: cpsw-default-pins { + pinctrl-single,pins = < + /* Slave 1 */ +@@ -372,6 +239,7 @@ + pinctrl-0 = <&uart0_pins>; + + status = "okay"; ++ symlink = "bone/uart/0"; + }; + + &usb0 { +@@ -389,6 +257,7 @@ + pinctrl-0 = <&i2c2_pins>; + status = "okay"; + clock-frequency = <100000>; ++ symlink = "bone/i2c/2"; + }; + + &cpsw_port1 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-osd335x-common.dtsi b/arch/arm/boot/dts/ti/omap/am335x-osd335x-common.dtsi +--- a/arch/arm/boot/dts/ti/omap/am335x-osd335x-common.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-osd335x-common.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -49,6 +49,7 @@ + + status = "okay"; + clock-frequency = <400000>; ++ symlink = "bone/i2c/0"; + + tps: tps@24 { + reg = <0x24>; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts b/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-pocketbeagle.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -8,6 +8,7 @@ + + #include "am33xx.dtsi" + #include "am335x-osd335x-common.dtsi" ++#include + + / { + model = "TI AM335x PocketBeagle"; +@@ -15,6 +16,8 @@ + + chosen { + stdout-path = &uart0; ++ base_dtb = "am335x-pocketbeagle.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; + }; + + leds { +@@ -25,6 +28,8 @@ + + led-usr0 { + label = "beaglebone:green:usr0"; ++ color = ; ++ function = LED_FUNCTION_HEARTBEAT; + gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; +@@ -32,6 +37,8 @@ + + led-usr1 { + label = "beaglebone:green:usr1"; ++ color = ; ++ function = LED_FUNCTION_DISK_ACTIVITY; + gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; +@@ -39,6 +46,8 @@ + + led-usr2 { + label = "beaglebone:green:usr2"; ++ color = ; ++ function = LED_FUNCTION_CPU; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "cpu0"; + default-state = "off"; +@@ -46,6 +55,8 @@ + + led-usr3 { + label = "beaglebone:green:usr3"; ++ color = ; ++ function = LED_FUNCTION_INDICATOR; + gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; +@@ -112,7 +123,7 @@ + "P2.24", + "P2.33", + "P2.22", +- "P2.18", ++ "P2.18 [PRU0.15i]", + "NC", + "NC", + "P2.01 [PWM1A]", +@@ -208,11 +219,6 @@ + compatible = "pinconf-single"; + pinctrl-names = "default"; + +- pinctrl-0 = < &P2_03_gpio &P1_34_gpio &P2_19_gpio &P2_24_gpio +- &P2_33_gpio &P2_22_gpio &P2_18_gpio &P2_10_gpio +- &P2_06_gpio &P2_04_gpio &P2_02_gpio &P2_08_gpio +- &P2_17_gpio >; +- + /* P2_03 (ZCZ ball T10) gpio0_23 0x824 PIN 9 */ + P2_03_gpio: P2-03-gpio-pins { + pinctrl-single,pins = < +@@ -267,10 +273,10 @@ + pinctrl-single,bias-pulldown = < 0x10 0x00 0x10 0x18>; + }; + +- /* P2_18 (ZCZ ball U13) gpio1_15 0x83c PIN 15 */ +- P2_18_gpio: P2-18-gpio-pins { ++ /* P2_20 (ZCZ ball T13) gpio2_00 0x888 */ ++ P2_20_gpio: P2-20-gpio-pins { + pinctrl-single,pins = < +- AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE7) ++ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT_PULLUP, MUX_MODE7) + >; + pinctrl-single,bias-pullup = < 0x10 0x10 0x00 0x18>; + pinctrl-single,bias-pulldown = < 0x10 0x00 0x10 0x18>; +@@ -401,6 +407,27 @@ + AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLDOWN, MUX_MODE6) /* (U17) gpmc_wpn.uart4_txd */ + >; + }; ++ ++ pru0_pins: pinmux-pru0-pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT_PULLUP, MUX_MODE5)/* (D14) xdma_event_intr1.pr1_pru0_pru_r31_16 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE5)/* (A14) mcasp0_ahclkx.pr1_pru0_pru_r30_7 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (B12) mcasp0_acklr.pr1_pru0_pru_r30_4 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (B13) mcasp0_fsx.pr1_pru0_pru_r30_1 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE6) /* (U13) gpmc_ad15.pr1_pru0_pru_r31_15 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR1, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (D13) mcasp0_axr1.pr1_pru0_pru_r30_6 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE5)/* (C12) mcasp0_ahclkr.pr1_pru0_pru_r30_3 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (D12) mcasp0_axr0.pr1_pru0_pru_r30_2 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (C13) mcasp0_fsr.pr1_pru0_pru_r30_5 */ ++ >; ++ }; ++ ++ pru1_pins: pinmux-pru1-pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE5)/*(R6) lcd_ac_bias_en.pr1_pru1_pru_r30_11 */ ++ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE5) /* (V5) lcd_pclk.pr1_pru1_pru_r30_10 */ ++ >; ++ }; + }; + + &epwmss0 { +@@ -482,3 +509,17 @@ + &usb1 { + dr_mode = "host"; + }; ++ ++&pruss_tm { ++ status = "okay"; ++}; ++ ++&pru0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pru0_pins>; ++}; ++ ++&pru1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pru1_pins>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/AM335X-PRU-UIO-00A0.dtso b/arch/arm/boot/dts/ti/omap/AM335X-PRU-UIO-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/AM335X-PRU-UIO-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/AM335X-PRU-UIO-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,28 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ AM335X-PRU-UIO-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++ ++&pruss_tm { ++ status = "okay"; ++}; ++ ++&pruss { ++ compatible = "ti,pruss-v2"; ++ ti,pintc-offset = <0x20000>; ++ interrupt-parent = <&intc>; ++ interrupts = <20 21 22 23 24 25 26 27>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe.dts b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -14,6 +14,11 @@ + / { + model = "SanCloud BeagleBone Enhanced"; + compatible = "sancloud,am335x-boneenhanced", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-sancloud-bbe.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; + + &am33xx_pinmux { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-extended-wifi.dts b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-extended-wifi.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-extended-wifi.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-extended-wifi.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * Copyright (C) 2021 Sancloud Ltd +- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ + */ + /dts-v1/; + +@@ -18,6 +18,11 @@ + "ti,am335x-bone", + "ti,am33xx"; + ++ chosen { ++ base_dtb = "am335x-sancloud-bbe-extended-wifi.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; ++ + wlan_en_reg: fixedregulator@2 { + compatible = "regulator-fixed"; + regulator-name = "wlan-en-regulator"; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-lite.dts b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-lite.dts +--- a/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-lite.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am335x-sancloud-bbe-lite.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* +- * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ + * Copyright (C) 2021 SanCloud Ltd + */ + /dts-v1/; +@@ -16,6 +16,11 @@ + "ti,am335x-bone-black", + "ti,am335x-bone", + "ti,am33xx"; ++ ++ chosen { ++ base_dtb = "am335x-sancloud-bbe-lite.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; + + &am33xx_pinmux { +@@ -42,6 +47,7 @@ + #size-cells = <0>; + + compatible = "micron,spi-authenta"; ++ symlink = "bone/spi/0.0"; + + reg = <0>; + spi-max-frequency = <16000000>; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am33xx.dtsi b/arch/arm/boot/dts/ti/omap/am33xx.dtsi +--- a/arch/arm/boot/dts/ti/omap/am33xx.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am33xx.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -640,10 +640,11 @@ + #size-cells = <1>; + ranges = <0 0x56000000 0x1000000>; + +- /* +- * Closed source PowerVR driver, no child device +- * binding or driver in mainline +- */ ++ gpu@0 { ++ compatible = "ti,omap3630-gpu", "img,powervr-sgx530"; ++ reg = <0x0 0x10000>; /* 64kB */ ++ interrupts = <37>; ++ }; + }; + }; + }; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am33xx-l4.dtsi b/arch/arm/boot/dts/ti/omap/am33xx-l4.dtsi +--- a/arch/arm/boot/dts/ti/omap/am33xx-l4.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am33xx-l4.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -302,7 +302,7 @@ + am33xx_pinmux: pinmux@800 { + compatible = "pinctrl-single"; + reg = <0x800 0x238>; +- #pinctrl-cells = <2>; ++ #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x7f>; + }; +@@ -854,7 +854,7 @@ + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x300000 0x80000>; +- status = "disabled"; ++ status = "okay"; + + pruss: pruss@0 { + compatible = "ti,am3356-pruss"; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts b/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts +--- a/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am5729-beagleboneai.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * Copyright (C) 2014-2019 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2014-2019 Texas Instruments Incorporated - https://www.ti.com/ + */ + + /dts-v1/; +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include "bbai-bone-buses.dtsi" + + / { + model = "BeagleBoard.org BeagleBone AI"; +@@ -22,10 +23,19 @@ + rtc0 = &tps659038_rtc; + rtc1 = &rtc; + display0 = &hdmi_conn; ++ mmc0 = &mmc1; ++ mmc1 = &mmc2; ++ mmc2 = &mmc4; ++ i2c0 = &i2c1; ++ i2c1 = &i2c5; ++ i2c2 = &i2c4; ++ i2c3 = &i2c3; + }; + + chosen { + stdout-path = &uart1; ++ base_dtb = "am5729-beagleboneai.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; + }; + + memory@0 { +@@ -103,6 +113,8 @@ + + leds { + compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&led_pins_default>; + + led0 { + label = "beaglebone:green:usr0"; +@@ -186,10 +198,14 @@ + emmc_pwrseq: emmc_pwrseq { + compatible = "mmc-pwrseq-emmc"; + reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_pwrseq_pins_default>; + }; + + brcmf_pwrseq: brcmf_pwrseq { + compatible = "mmc-pwrseq-simple"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&brcmf_pwrseq_pins_default>; + reset-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>, /* BT-REG-ON */ + <&gpio3 18 GPIO_ACTIVE_LOW>; /* WL-REG-ON */ + }; +@@ -197,13 +213,85 @@ + extcon_usb1: extcon_usb1 { + compatible = "linux,extcon-usb-gpio"; + ti,enable-id-detection; +- id-gpio = <&gpio3 13 GPIO_ACTIVE_HIGH>; ++ id-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&extcon_usb1_pins_default>; ++ }; ++}; ++ ++&dra7_pmx_core { ++ extcon_usb1_pins_default: extcon_usb1_pins_default { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x3518, PIN_INPUT | MUX_MODE14) /* AG2: vin1a_d9.gpio3_13 - USR0 */ ++ >; ++ }; ++ ++ led_pins_default: led_pins_default { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x3528, PIN_OUTPUT | MUX_MODE14) /* AF6: vin1a_d13.gpio3_17 - USR0 */ ++ DRA7XX_CORE_IOPAD(0x36c0, PIN_OUTPUT | MUX_MODE14) /* J11: mcasp1_axr3.gpio5_5 - USR1 */ ++ DRA7XX_CORE_IOPAD(0x3520, PIN_OUTPUT | MUX_MODE14) /* AG5: vin1a_d12.gpio3_15 - USR2 */ ++ DRA7XX_CORE_IOPAD(0x351c, PIN_OUTPUT | MUX_MODE14) /* AG3: vin1a_d10.gpio3_14 - USR3 */ ++ DRA7XX_CORE_IOPAD(0x3500, PIN_OUTPUT | MUX_MODE14) /* AH6: vin1a_d3.gpio3_7 - USR4 */ ++ >; ++ }; ++ ++ emmc_pwrseq_pins_default: emmc_pwrseq_pins_default { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x36c8, PIN_OUTPUT_PULLUP | MUX_MODE14) /* F13: mcasp1_axr5.gpio5_7 - eMMC_RSTn */ ++ >; ++ }; ++ ++ brcmf_pwrseq_pins_default: brcmf_pwrseq_pins_default { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x352c, PIN_OUTPUT_PULLUP | MUX_MODE14) /* AF3: vin1a_d14.gpio3_18 - WL_REG_ON */ ++ DRA7XX_CORE_IOPAD(0x353c, PIN_OUTPUT_PULLUP | MUX_MODE14) /* AE5: vin1a_d18.gpio3_22 - BT_REG_ON */ ++ >; ++ }; ++ ++ wifibt_extra_pins_default: wifibt_extra_pins_default { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x3540, PIN_INPUT | MUX_MODE14) /* AE1: vin1a_d19.gpio3_23 - WL_HOST_WAKE */ ++ DRA7XX_CORE_IOPAD(0x3450, PIN_INPUT | MUX_MODE8) /* P6: vin1a_d20.uart6_rxd - UART6_RXD */ ++ DRA7XX_CORE_IOPAD(0x3454, PIN_INPUT | MUX_MODE8) /* R9: vin1a_d21.uart6_txd - UART6_TXD */ ++ DRA7XX_CORE_IOPAD(0x3458, PIN_INPUT | MUX_MODE8) /* R5: vin1a_d22.uart6_ctsn - UART6_CTSN */ ++ DRA7XX_CORE_IOPAD(0x345c, PIN_INPUT | MUX_MODE8) /* P5: vin1a_d23.uart6_rtsn - UART6_RTSN */ ++ DRA7XX_CORE_IOPAD(0x3534, PIN_INPUT_PULLDOWN | MUX_MODE14) /* AF1: vin1a_d16.gpio3_20 - BT_HOST_WAKE */ ++ DRA7XX_CORE_IOPAD(0x3538, PIN_OUTPUT_PULLDOWN | MUX_MODE14) /* AE3: vin1a_d6.gpio3_21 - BT_WAKE */ ++ >; ++ }; ++ ++ adc_pins_default: adc_pins_default { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x3550, PIN_OUTPUT | MUX_MODE14) /* AD3: vin1a_d23.gpio3_27 - VDD_ADC_SEL */ ++ DRA7XX_CORE_IOPAD(0x34DC, PIN_INPUT_PULLUP | MUX_MODE14) /* AG8: vin1a_clk0.gpio2_30 - INT_ADC */ ++ >; ++ }; ++ ++ pmic_pins_default: pmic_pins_default { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x3690, PIN_INPUT_PULLUP | MUX_MODE14) /* F21: gpio6_16.gpio6_16 - PMIC_INT */ ++ >; ++ }; ++ ++ hdmi_pins_default: hdmi_pins_default { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* C25: i2c2_sda.hdmi1_ddc_scl - HDMI_DDC_SCL */ ++ DRA7XX_CORE_IOPAD(0x380C, PIN_INPUT | MUX_MODE1) /* F17: i2c2_scl.hdmi1_ddc_sda - HDMI_DDC_SDA */ ++ DRA7XX_CORE_IOPAD(0x37BC, PIN_INPUT | MUX_MODE6) /* B20: spi1_cs3.hdmi1_cec - HDMI_DDC_CEC */ ++#if 0 ++ DRA7XX_CORE_IOPAD(0x37B8, PIN_INPUT | MUX_MODE6) /* B21: spi1_cs2.hdmi1_hpd - HDMI_DDC_HPD */ ++#else ++ DRA7XX_CORE_IOPAD(0x37B8, PIN_INPUT | MUX_MODE14) /* B21: spi1_cs2.gpio7_12 - HDMI_DDC_HPD */ ++#endif ++ >; + }; + }; + + &i2c1 { + status = "okay"; + clock-frequency = <400000>; ++ symlink = "bone/i2c/0"; + + tps659038: tps659038@58 { + compatible = "ti,tps659038"; +@@ -211,6 +299,9 @@ + interrupt-parent = <&gpio6>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; + ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_pins_default>; ++ + #interrupt-cells = <2>; + interrupt-controller; + +@@ -415,7 +506,6 @@ + reg = <0x41>; + interrupts = <30 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&gpio2>; +- interrupt-controller; + id = <0>; + blocks = <0x5>; + irq-trigger = <0x1>; +@@ -424,6 +514,9 @@ + st,adc-freq = <1>; /* 3.25 MHz ADC clock speed */ + st,sample-time = <4>; /* ADC converstion time: 80 clocks */ + ++ pinctrl-names = "default"; ++ pinctrl-0 = <&adc_pins_default>; ++ + stmpe_adc { + compatible = "st,stmpe-adc"; + st,norequest-mask = <0x00>; /* mask any channels to be used by touchscreen */ +@@ -462,6 +555,11 @@ + #pwm-cells = <2>; + }; + }; ++ ++ eeprom: eeprom@50 { ++ compatible = "atmel,24c32"; ++ reg = <0x50>; ++ }; + }; + + &mcspi3 { +@@ -486,6 +584,7 @@ + + &uart1 { + status = "okay"; ++ symlink = "bone/uart/0"; + }; + + &davinci_mdio_sw { +@@ -550,7 +649,11 @@ + ti,needs-special-reset; + dmas = <&sdma_xbar 47>, <&sdma_xbar 48>; + dma-names = "tx", "rx"; +- ++ pinctrl-names = "default", "hs", "ddr_1_8v", "hs200_1_8v"; ++ pinctrl-0 = <&mmc2_pins_default>; ++ pinctrl-1 = <&mmc2_pins_hs>; ++ pinctrl-2 = <&mmc2_pins_ddr_rev20>; ++ pinctrl-3 = <&mmc2_pins_hs200>; + }; + + &mmc4 { +@@ -563,6 +666,10 @@ + /* DDR50: DDR up to 50 MHz (1.8 V signaling). */ + status = "okay"; + ++ pinctrl-names = "default", "hs"; ++ pinctrl-0 = <&mmc4_pins_default &wifibt_extra_pins_default>; ++ pinctrl-1 = <&mmc4_pins_hs &wifibt_extra_pins_default>; ++ + ti,needs-special-reset; + vmmc-supply = <&vdd_3v3>; + cap-power-off-card; +@@ -622,6 +729,8 @@ + &hdmi { + status = "okay"; + vdda-supply = <&vdd_1v8_phy_ldo4>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmi_pins_default>; + + port { + hdmi_out: endpoint { +@@ -675,6 +784,7 @@ + &i2c4 { + status = "okay"; + clock-frequency = <100000>; ++ symlink = "bone/i2c/2"; + }; + + &ipu2 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15.dts b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15.dts +--- a/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -8,6 +8,11 @@ + / { + /* NOTE: This describes the "original" pre-production A2 revision */ + model = "TI AM5728 BeagleBoard-X15"; ++ ++ chosen { ++ base_dtb = "am57xx-beagle-x15.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; + + &tpd12s015 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revb1.dts b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revb1.dts +--- a/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revb1.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revb1.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -7,6 +7,11 @@ + + / { + model = "TI AM5728 BeagleBoard-X15 rev B1"; ++ ++ chosen { ++ base_dtb = "am57xx-beagle-x15-revb1.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; + + &tpd12s015 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revc.dts b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revc.dts +--- a/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revc.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/am57xx-beagle-x15-revc.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -7,6 +7,11 @@ + + / { + model = "TI AM5728 BeagleBoard-X15 rev C"; ++ ++ chosen { ++ base_dtb = "am57xx-beagle-x15-revc.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; ++ }; + }; + + &tpd12s015 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-ADC-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-ADC-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-ADC-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-ADC-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,112 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-ADC-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++&tscadc { ++ status = "okay"; ++ adc { ++ // Configure one or more (up to 8) steps for the adc to execute: ++ ++ ++ // For each step, the channel to sample. ++ // range: 0 .. 7 ++ ti,adc-channels = <0 1 2 3 4 5 6 7>; ++ // ++ // BeagleBone Black (and most other variants): ++ // ch 0 P9.39 ++ // ch 1 P9.40 ++ // ch 2 P9.37 ++ // ch 3 P9.38 ++ // ch 4 P9.33 ++ // ch 5 P9.36 ++ // ch 6 P9.35 ++ // ch 7 measures 0.5 * VDD_3V3B with 2.4 kΩ source impedance ++ // ++ // PocketBeagle: ++ // ch 0 P1.19 ++ // ch 1 P1.21 ++ // ch 2 P1.23 ++ // ch 3 P1.25 ++ // ch 4 P1.27 ++ // ch 5 P2.35 via 10k/10k voltage divider ++ // ch 6 P1.02 via 10k/10k voltage divider ++ // ch 7 P2.36 via pmic mux ++ // ++ // The divider used on PocketBeagle channels 5 and 6 makes the effective voltage V_eff and ++ // source impedance Z_eff seen by the adc on these channels depend on the voltage V_src and ++ // impedance Z_src of the source connected to the corresponding pin as follows: ++ // ++ // V_eff = V_src / (2 + Z_src / (10 kΩ)) ++ // Z_eff = 5 kΩ * (1 + Z_src / (Z_src + 20 kΩ)) ++ // ≈ 5 kΩ + Z_src / 4 for small values of Z_src (up to 2 kΩ or so) ++ ++ ++ // For each step, number of adc clock cycles to wait between setting up muxes and sampling. ++ // range: 0 .. 262143 ++ // optional, default is 152 (XXX but why?!) ++ ti,chan-step-opendelay = <152 152 152 152 152 152 152 152>; ++ //` ++ // XXX is there any purpose to set this nonzero other than to fine-tune the sample rate? ++ ++ ++ // For each step, how many times it should sample to average. ++ // range: 1 .. 16, must be power of two (i.e. 1, 2, 4, 8, or 16) ++ // optional, default is 16 ++ ti,chan-step-avg = <16 16 16 16 16 16 16 16>; ++ // ++ // If you're using periodic sampling (using the iio block device rather than sysfs) then ++ // you should consider setting this to 1 and if desired reduce the samplerate in userspace ++ // instead since averaging isn't a particularly good low-pass filter. ++ // ++ // If you're using sysfs to occasionally read a value, then the default value of 16 will ++ // still get you the most accurate readings. ++ ++ ++ // For each step, number of adc clock cycles to sample minus two. ++ // range: 0 .. 255 (resulting in sampling time of 2 .. 257 cycles) ++ // optional, default is 0 ++ ti,chan-step-sampledelay = <0 0 0 0 0 0 0 0>; ++ // ++ // If this is set too low, accuracy will deteriorate when the thing you're measuring has a ++ // high source impedance. The maximum source impedance recommended (by erratum 1.0.32) is: ++ // (2 + sampledelay) * 2.873 kΩ - 0.2 kΩ ++ // which means that the default should be fine for source impedance up to 5.5 kΩ. ++ // ++ // (This seems to ensure the sampling time is at least 21 times the RC constant, based on ++ // the 5.5 pF nominal capacitance specified in the datasheet.) ++ ++ ++ // After sampling, conversion time is 13 adc clock cycles. ++ // ++ // The adc clock frequency is 3 MHz, therefore the total time per step in microseconds is: ++ // ( opendelay + avg * ( 2 + sampledelay + 13 ) ) / 3 ++ // ++ // If all steps use the same timings then the sample rate will be: ++ // 3 MHz / ( opendelay + avg * ( 2 + sampledelay + 13 ) ) / number_of_steps ++ // ++ // The highest samplerate obtainable (avg=1, opendelay=0, sampledelay=0) is therefore: ++ // 200 kHz / number_of_steps ++ // = 25 kHz when using all 8 steps. ++ // ++ // Using avg=16 reduces that to: ++ // 12.5 kHz / number_of_steps ++ // = 1.5625 kHz when using all 8 steps. ++ // ++ // Using the default values (avg=16, opendelay=152, sampledelay=0) reduces that to: ++ // 7.653 kHz / number_of_steps ++ // = 0.9566 kHz when using all 8 steps. ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/bbai-bone-buses.dtsi b/arch/arm/boot/dts/ti/omap/bbai-bone-buses.dtsi +--- a/arch/arm/boot/dts/ti/omap/bbai-bone-buses.dtsi 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/bbai-bone-buses.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,75 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 Deepak Khatri ++ * Copyright (C) 2021 Robert Nelson ++ * See Cape Interface Spec page for more info on Bone Buses ++ * https://elinux.org/Beagleboard:BeagleBone_cape_interface_spec ++ * https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html ++ */ ++ ++#include ++#include ++ ++// For dummy refrence when peripheral is not available. ++&{/} { ++ not_available: not_available { ++ // Use ¬_available phandle when bus not available! ++ // This node is responsible to create these entries, ++ // /sys/firmware/devicetree/base/__symbols__/not_available ++ // /sys/firmware/devicetree/base/not_available ++ }; ++}; ++ ++// For compatible bone pinmuxing ++bone_pinmux: &dra7_pmx_core { ++ bborg_comms_can_pins: pinmux_comms_can_pins { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x368C, PIN_INPUT_PULLUP | MUX_MODE2) /* P9_24: F20: gpio6_15.dcan2_rx */ ++ DRA7XX_CORE_IOPAD(0x3688, PIN_OUTPUT_PULLUP | MUX_MODE2) /* P9_26A: E21: gpio6_14.dcan2_tx */ ++ DRA7XX_CORE_IOPAD(0x3544, PIN_OUTPUT | MUX_MODE15) /* P9_26B: AE2: vin1a_d20.off */ ++ >; ++ }; ++ ++ bborg_comms_rs485_pins: pinmux_comms_rs485_pins { ++ pinctrl-single,pins = < ++ DRA7XX_CORE_IOPAD(0x3730, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4) /* P9_13A: C17: mcasp3_axr1.uart5_txd */ ++ DRA7XX_CORE_IOPAD(0x3680, PIN_OUTPUT | MUX_MODE15) /* P9_13B: AB10: usb1_drvvbus.off */ ++ DRA7XX_CORE_IOPAD(0x372C, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4) /* P9_11A: B19: mcasp3_axr0.uart5_rxd */ ++ DRA7XX_CORE_IOPAD(0x3620, PIN_OUTPUT | MUX_MODE15) /* P9_11B: B8: vout1_d17.off */ ++ >; ++ }; ++}; ++ ++// UART ++// https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html#uart ++bone_uart_1: &uart10 { ++ symlink = "bone/uart/1"; ++}; ++ ++bone_uart_2: &uart3 { ++ symlink = "bone/uart/2"; ++}; ++ ++bone_uart_3: ¬_available { ++ // not available on BBAI ++}; ++ ++bone_uart_4: &uart5 { ++ symlink = "bone/uart/4"; ++ status = "disabled"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bborg_comms_rs485_pins>; ++}; ++ ++// CAN ++// https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html#can ++bone_can_0: ¬_available { ++ // Not available on BBAI ++}; ++ ++bone_can_1: &dcan2 { ++ symlink = "bone/can/1"; ++ status = "disabled"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bborg_comms_can_pins>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-BBBW-WL1835-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-BBBW-WL1835-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-BBBW-WL1835-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-BBBW-WL1835-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,123 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-BBBW-WL1835-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++&{/} { ++ model = "TI AM335x BeagleBone Black Wireless"; ++ compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ wlan_en_reg: fixedregulator@2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ startup-delay-us= <70000>; ++ ++ /* WL_EN */ ++ gpio = <&gpio3 9 0>; ++ enable-active-high; ++ }; ++}; ++ ++&am33xx_pinmux { ++ bt_pins: pinmux_bt_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_txd0.gpio0_28 - BT_EN */ ++ >; ++ }; ++ ++ mmc3_pins: pinmux_mmc3_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */ ++ >; ++ }; ++ ++ uart3_pins: pinmux_uart3_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gmii1_rxd3.uart3_rxd */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* gmii1_rxd2.uart3_txd */ ++ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3) /* mdio_data.uart3_ctsn */ ++ AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* mdio_clk.uart3_rtsn */ ++ >; ++ }; ++ ++ wl18xx_pins: pinmux_wl18xx_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gmii1_txclk.gpio3_9 WL_EN */ ++ AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_refclk.gpio0_29 WL_IRQ */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_rxclk.gpio3_10 LS_BUF_EN */ ++ >; ++ }; ++}; ++ ++&mac_sw { ++ /delete-property/pinctrl-names; ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-1; ++ status = "disabled"; ++}; ++ ++&mmc3 { ++ dmas = <&edma_xbar 12 0 1 ++ &edma_xbar 13 0 2>; ++ dma-names = "tx", "rx"; ++ status = "okay"; ++ vmmc-supply = <&wlan_en_reg>; ++ bus-width = <4>; ++ non-removable; ++ cap-power-off-card; ++ keep-power-in-suspend; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc3_pins &wl18xx_pins>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wlcore: wlcore@2 { ++ compatible = "ti,wl1835"; ++ reg = <2>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <29 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; ++ ++&uart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart3_pins &bt_pins>; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "ti,wl1835-st"; ++ enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>; ++ }; ++}; ++ ++&gpio3 { ++ ls-buf-en-hog { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LS_BUF_EN"; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-BBGG-WL1835-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-BBGG-WL1835-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-BBGG-WL1835-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-BBGG-WL1835-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,249 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-BBGG-WL1835-00A0.kernel = __TIMESTAMP__; ++ wl1835_bt = "S3-texas-300000"; ++ }; ++}; ++ ++&{/} { ++ model = "SeeedStudio BeagleBone Green Gateway"; ++ compatible = "ti,am335x-bone-green-gateway", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++ ++ aliases { ++ rtc0 = &extrtc; ++ rtc1 = "/ocp/rtc@44e3e000"; ++ }; ++ ++ wlan_en_reg: fixedregulator@2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ startup-delay-us= <70000>; ++ ++ /* WL_EN */ ++ gpio = <&gpio3 9 0>; ++ enable-active-high; ++ }; ++ ++ leds { ++ pinctrl-names = "default"; ++ //pinctrl-0 = <&user_leds_s0>; ++ pinctrl-0 = <&user_leds_s0 &bt_pins>; ++ ++ compatible = "gpio-leds"; ++ ++ led2 { ++ label = "beaglebone:green:usr0"; ++ gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ default-state = "off"; ++ }; ++ ++ led3 { ++ label = "beaglebone:green:usr1"; ++ gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc0"; ++ default-state = "off"; ++ }; ++ ++ led4 { ++ label = "beaglebone:green:usr2"; ++ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "cpu0"; ++ default-state = "off"; ++ }; ++ ++ led5 { ++ label = "beaglebone:green:usr3"; ++ gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc1"; ++ default-state = "off"; ++ }; ++ ++ led6 { ++ label = "beaglebone:green:usr4"; ++ gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "netdev"; ++ default-state = "off"; ++ }; ++ ++ wl18xx_bt_en: led7 { ++ label = "wl18xx_bt_en"; ++ gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++}; ++ ++&am33xx_pinmux { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usbhost_pins>; ++ ++ user_leds_s0: user_leds_s0 { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a6.gpio1_22 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a7.gpio1_23 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a8.gpio1_24 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* WL_Active_LED / USR4 */ ++ >; ++ }; ++ ++ bt_pins: pinmux_bt_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gmii1_txd0.gpio0_28 - BT_EN */ ++ >; ++ }; ++ ++ mmc3_pins: pinmux_mmc3_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */ ++ >; ++ }; ++ ++ uart2_grove_pins: pinmux_uart2_grove_pins { ++ pinctrl-single,pins = < ++ AM33XX_IOPAD(0x90c, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6) ++ AM33XX_IOPAD(0x910, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6) ++ >; ++ }; ++ ++ uart3_pins: pinmux_uart3_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gmii1_rxd3.uart3_rxd */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* gmii1_rxd2.uart3_txd */ ++ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3) /* mdio_data.uart3_ctsn */ ++ AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* mdio_clk.uart3_rtsn */ ++ >; ++ }; ++ ++ usbhost_pins: pinmux_usbhost_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_txd1.gpio0[21] */ ++ >; ++ }; ++ ++ wl18xx_pins: pinmux_wl18xx_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gmii1_txclk.gpio3_9 WL_EN */ ++ AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7) /* rmii1_refclk.gpio0_29 WL_IRQ */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gmii1_rxclk.gpio3_10 LS_BUF_EN */ ++ >; ++ }; ++}; ++ ++&mac_sw { ++ /delete-property/pinctrl-names; ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-1; ++ status = "disabled"; ++}; ++ ++&mmc3 { ++ dmas = <&edma_xbar 12 0 1 ++ &edma_xbar 13 0 2>; ++ dma-names = "tx", "rx"; ++ status = "okay"; ++ vmmc-supply = <&wlan_en_reg>; ++ bus-width = <4>; ++ non-removable; ++ cap-power-off-card; ++ keep-power-in-suspend; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc3_pins &wl18xx_pins>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wlcore: wlcore@2 { ++ compatible = "ti,wl1835"; ++ reg = <2>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <29 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; ++ ++&uart2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart2_grove_pins>; ++ status = "okay"; ++}; ++ ++&uart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart3_pins>; ++ //pinctrl-0 = <&uart3_pins &bt_pins>; ++ status = "okay"; ++ ++ //bluetooth { ++ // compatible = "ti,wl1835-st"; ++ // enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>; ++ //}; ++}; ++ ++&i2c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ extrtc: rtc@68 { ++ compatible = "dallas,ds1340"; ++ reg = <0x68>; ++ }; ++}; ++ ++// (K16) gmii1_txd1.gpio0[21] ++&gpio0 { ++ usb-reset-hog { ++ gpio-hog; ++ gpios = <21 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "usb_reset"; ++ }; ++}; ++ ++&gpio3 { ++ ls-buf-en-hog { ++ gpio-hog; ++ gpios = <10 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LS_BUF_EN"; ++ }; ++}; ++ ++&usb1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hub@1 { ++ compatible = "usb424,9512"; ++ reg = <1>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ethernet: ethernet@1 { ++ compatible = "usb424,ec00"; ++ reg = <1>; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-BBGW-WL1835-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-BBGW-WL1835-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-BBGW-WL1835-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-BBGW-WL1835-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,217 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-BBGW-WL1835-00A0.kernel = __TIMESTAMP__; ++ wl1835_bt = "S3-texas-300000"; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_12_pinmux { status = "disabled"; }; /* gpmc_ad12.gpio1_28 BT_EN */ ++ P8_12_pinmux { status = "disabled"; }; /* gpmc_ad12.mmc2_dat0 */ ++ P8_11_pinmux { status = "disabled"; }; /* gpmc_ad13.mmc2_dat1 */ ++ P8_16_pinmux { status = "disabled"; }; /* gpmc_ad14.mmc2_dat2 */ ++ P8_15_pinmux { status = "disabled"; }; /* gpmc_ad15.mmc2_dat3 */ ++ ++ P8_18_pinmux { status = "disabled"; }; /* gpmc_clk.mmc2_clk */ ++ ++ //Audio... ++ P9_28_pinmux { status = "disabled"; }; ++ P9_29_pinmux { status = "disabled"; }; ++ P9_31_pinmux { status = "disabled"; }; ++ ++ /* wl1835 */ ++ P8_14_pinmux { status = "disabled"; }; /* wl1835: wl_en */ ++ P8_17_pinmux { status = "disabled"; }; /* wl1835: wl_irq */ ++ P8_26_pinmux { status = "disabled"; }; /* wl1835: LS_BUF_EN */ ++ P9_30_pinmux { status = "disabled"; }; /* wl1835: MCASP0_AHCLKR */ ++}; ++ ++&{/} { ++ model = "TI AM335x BeagleBone Green Wireless"; ++ compatible = "ti,am335x-bone-green-wireless", "ti,am335x-bone-green", "ti,am335x-bone", "ti,am33xx"; ++ ++ wlan_en_reg: fixedregulator@2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "wlan-en-regulator"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ startup-delay-us= <70000>; ++ ++ /* WL_EN */ ++ gpio = <&gpio0 26 0>; ++ enable-active-high; ++ }; ++ ++ leds { ++ pinctrl-names = "default"; ++ //pinctrl-0 = <&user_leds_s0>; ++ pinctrl-0 = <&user_leds_s0 &bt_pins>; ++ ++ compatible = "gpio-leds"; ++ ++ led2 { ++ label = "beaglebone:green:usr0"; ++ gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ default-state = "off"; ++ }; ++ ++ led3 { ++ label = "beaglebone:green:usr1"; ++ gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc0"; ++ default-state = "off"; ++ }; ++ ++ led4 { ++ label = "beaglebone:green:usr2"; ++ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "cpu0"; ++ default-state = "off"; ++ }; ++ ++ led5 { ++ label = "beaglebone:green:usr3"; ++ gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc1"; ++ default-state = "off"; ++ }; ++ ++ wl18xx_bt_en: led7 { ++ label = "wl18xx_bt_en"; ++ gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++}; ++ ++&am33xx_pinmux { ++ user_leds_s0: user_leds_s0 { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a5.gpio1_21 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a6.gpio1_22 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a7.gpio1_23 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_a8.gpio1_24 */ ++ >; ++ }; ++ ++ bt_pins: pinmux_bt_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_ad12.gpio1_28 BT_EN */ ++ >; ++ }; ++ ++ mmc3_pins: pinmux_mmc3_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_ad12.mmc2_dat0 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_ad13.mmc2_dat1 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_ad14.mmc2_dat2 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_ad15.mmc2_dat3 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_csn3.mmc2_cmd */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT_PULLUP, MUX_MODE3) /* gpmc_clk.mmc2_clk */ ++ >; ++ }; ++ ++ uart3_pins: pinmux_uart3_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gmii1_rxd3.uart3_rxd */ ++ AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1) /* gmii1_rxd2.uart3_txd */ ++ AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3) /* mdio_data.uart3_ctsn */ ++ AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3) /* mdio_clk.uart3_rtsn */ ++ >; ++ }; ++ ++ wl18xx_pins: pinmux_wl18xx_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_ad10.gpio0_26 WL_EN */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLDOWN, MUX_MODE7) /* gpmc_ad11.gpio0_27 WL_IRQ */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_csn0.gpio1_29 LS_BUF_EN */ ++ >; ++ }; ++}; ++ ++&mac_sw { ++ /delete-property/pinctrl-names; ++ /delete-property/pinctrl-0; ++ /delete-property/pinctrl-1; ++ status = "disabled"; ++}; ++ ++&mmc3 { ++ dmas = <&edma_xbar 12 0 1 ++ &edma_xbar 13 0 2>; ++ dma-names = "tx", "rx"; ++ status = "okay"; ++ vmmc-supply = <&wlan_en_reg>; ++ bus-width = <4>; ++ non-removable; ++ cap-power-off-card; ++ keep-power-in-suspend; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mmc3_pins &wl18xx_pins>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ wlcore: wlcore@2 { ++ compatible = "ti,wl1835"; ++ reg = <2>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <27 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; ++ ++&uart3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart3_pins>; ++ //pinctrl-0 = <&uart3_pins &bt_pins>; ++ status = "okay"; ++ ++ //bluetooth { ++ // compatible = "ti,wl1835-st"; ++ // enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; ++ //}; ++}; ++ ++&gpio1 { ++ ls-buf-en-hog { ++ gpio-hog; ++ gpios = <29 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "LS_BUF_EN"; ++ }; ++}; ++ ++/* BT_AUD_OUT from wl1835 has to be pulled low when WL_EN is activated.*/ ++/* in case it isn't, wilink8 ends up in one of the test modes that */ ++/* intruces various issues (elp wkaeup timeouts etc.) */ ++/* On the BBGW this pin is routed through the level shifter (U21) that */ ++/* introduces a pullup on the line and wilink8 ends up in a bad state. */ ++/* use a gpio hog to force this pin low. An alternative may be adding */ ++/* an external pulldown on U21 pin 4. */ ++ ++&gpio3 { ++ bt-aud-in-hog { ++ gpio-hog; ++ gpios = <16 GPIO_ACTIVE_HIGH>; ++ output-low; ++ line-name = "MCASP0_AHCLKR"; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-BONE-4D5R-01-00A1.dtso b/arch/arm/boot/dts/ti/omap/BB-BONE-4D5R-01-00A1.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-BONE-4D5R-01-00A1.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-BONE-4D5R-01-00A1.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,224 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-BONE-4D5R-01-00A1.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P8_45_pinmux { status = "disabled"; }; /* lcd: lcd_data0 */ ++ P8_46_pinmux { status = "disabled"; }; /* lcd: lcd_data1 */ ++ P8_43_pinmux { status = "disabled"; }; /* lcd: lcd_data2 */ ++ P8_44_pinmux { status = "disabled"; }; /* lcd: lcd_data3 */ ++ P8_41_pinmux { status = "disabled"; }; /* lcd: lcd_data4 */ ++ P8_42_pinmux { status = "disabled"; }; /* lcd: lcd_data5 */ ++ P8_39_pinmux { status = "disabled"; }; /* lcd: lcd_data6 */ ++ P8_40_pinmux { status = "disabled"; }; /* lcd: lcd_data7 */ ++ P8_37_pinmux { status = "disabled"; }; /* lcd: lcd_data8 */ ++ P8_38_pinmux { status = "disabled"; }; /* lcd: lcd_data9 */ ++ P8_36_pinmux { status = "disabled"; }; /* lcd: lcd_data10 */ ++ P8_34_pinmux { status = "disabled"; }; /* lcd: lcd_data11 */ ++ P8_35_pinmux { status = "disabled"; }; /* lcd: lcd_data12 */ ++ P8_33_pinmux { status = "disabled"; }; /* lcd: lcd_data13 */ ++ P8_31_pinmux { status = "disabled"; }; /* lcd: lcd_data14 */ ++ P8_32_pinmux { status = "disabled"; }; /* lcd: lcd_data15 */ ++ ++ P8_27_pinmux { status = "disabled"; }; /* lcd: lcd_vsync */ ++ P8_29_pinmux { status = "disabled"; }; /* lcd: lcd_hsync */ ++ P8_28_pinmux { status = "disabled"; }; /* lcd: lcd_pclk */ ++ P8_30_pinmux { status = "disabled"; }; /* lcd: lcd_ac_bias_en */ ++ ++ P9_27_pinmux { status = "disabled"; }; /* lcd: gpio3_19 DISPEN */ ++ ++ P9_14_pinmux { status = "disabled"; }; /* pwm: ehrpwm1a PWM_BL */ ++ ++ P9_18_pinmux { status = "disabled"; }; /* i2c1_sda */ ++ P9_17_pinmux { status = "disabled"; }; /* i2c1_scl */ ++ P9_26_pinmux { status = "disabled"; }; /* touch interrupt on gpio0_14 */ ++}; ++ ++&am33xx_pinmux { ++ bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT, MUX_MODE6) /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */ ++ >; ++ }; ++ ++ bb_lcd_lcd_pins: pinmux_bb_lcd_lcd_pins { ++ pinctrl-single,pins = < ++ /*LCD enable */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT, MUX_MODE7) /* mcasp0_fsr.gpio3_19, OUTPUT | MODE7 LCD DISEN */ ++ ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0) ++ ++ AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0) ++ >; ++ }; ++ ++ bb_i2c1_pins: pinmux_bb_i2c1_pins { ++ pinctrl-single,pins = < ++ AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | SLEWCTRL_SLOW | MUX_MODE2) /* spi0_d1.i2c1_sda */ ++ AM33XX_IOPAD(0x95C, PIN_INPUT_PULLUP | SLEWCTRL_SLOW | MUX_MODE2) /* spi0_cs0.i2c1_scl */ ++ >; ++ }; ++ ++ ar1021_pins: pinmux_ar1021_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE7) ++ >; ++ }; ++}; ++ ++&epwmss1 { ++ status = "okay"; ++}; ++ ++&ehrpwm1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_pwm_backlight_pins>; ++ status = "okay"; ++}; ++ ++&lcdc { ++ status = "okay"; ++ ++ blue-and-red-wiring = "straight"; ++ ++ //FIXME - LCD doesn't init... ++ //port { ++ // lcdc_0: endpoint@0 { ++ // remote-endpoint = <&panel_0>; ++ // }; ++ //}; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_i2c1_pins>; ++ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ar1021: ar1021@4d { ++ status = "okay"; ++ compatible = "microchip,ar1021-i2c"; ++ reg = <0x4d>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ar1021_pins>; ++ interrupt-parent = <&gpio0>; ++ interrupts = <14 IRQ_TYPE_LEVEL_HIGH>; ++ ++ touchscreen-offset-x=<250>; ++ touchscreen-offset-y=<300>; ++ ++ touchscreen-inverted-y; ++ }; ++}; ++ ++&{/} { ++ backlight: backlight { ++ status = "okay"; ++ compatible = "pwm-backlight"; ++ pwms = <&ehrpwm1 0 500000 0>; ++ brightness-levels = < ++ 0 1 2 3 4 5 6 7 8 9 ++ 10 11 12 13 14 15 16 17 18 19 ++ 20 21 22 23 24 25 26 27 28 29 ++ 30 31 32 33 34 35 36 37 38 39 ++ 40 41 42 43 44 45 46 47 48 49 ++ 50 51 52 53 54 55 56 57 58 59 ++ 60 61 62 63 64 65 66 67 68 69 ++ 70 71 72 73 74 75 76 77 78 79 ++ 80 81 82 83 84 85 86 87 88 89 ++ 90 91 92 93 94 95 96 97 98 99 ++ 100 ++ >; ++ default-brightness-level = <100>; ++ }; ++ ++ panel { ++ status = "okay"; ++ compatible = "ti,tilcdc,panel"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_lcd_pins>; ++ backlight = <&backlight>; ++ enable-gpios = <&gpio3 19 0>; ++ ++ //FIXME - LCD doesn't init... ++ //port { ++ // panel_0: endpoint@0 { ++ // remote-endpoint = <&lcdc_0>; ++ // }; ++ //}; ++ ++ panel-info { ++ ac-bias = <255>; ++ ac-bias-intrpt = <0>; ++ dma-burst-sz = <16>; ++ bpp = <16>; ++ fdd = <0x80>; ++ sync-edge = <0>; ++ sync-ctrl = <1>; ++ raster-order = <0>; ++ fifo-th = <0>; ++ }; ++ ++ display-timings { ++ native-mode = <&timing0>; ++ /* Settings for ThreeFive S9700RTWV35TR / LCD7 cape: */ ++ timing0: 800x480 { ++ clock-frequency = <30000000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <40>; ++ hback-porch = <40>; ++ hsync-len = <48>; ++ vback-porch = <30>; ++ vfront-porch = <13>; ++ vsync-len = <3>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ de-active = <1>; ++ pixelclk-active = <0>; ++ }; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-BONE-eMMC1-01-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-BONE-eMMC1-01-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-BONE-eMMC1-01-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-BONE-eMMC1-01-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,61 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-BONE-eMMC1-01-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P8_21_pinmux { status = "disabled"; }; /* mmc1_clk */ ++ P8_20_pinmux { status = "disabled"; }; /* mmc1_cmd */ ++ P8_25_pinmux { status = "disabled"; }; /* mmc1_dat0 */ ++ P8_24_pinmux { status = "disabled"; }; /* mmc1_dat1 */ ++ P8_05_pinmux { status = "disabled"; }; /* mmc1_dat2 */ ++ P8_06_pinmux { status = "disabled"; }; /* mmc1_dat3 */ ++ P8_23_pinmux { status = "disabled"; }; /* mmc1_dat4 */ ++ P8_22_pinmux { status = "disabled"; }; /* mmc1_dat5 */ ++ P8_03_pinmux { status = "disabled"; }; /* mmc1_dat6 */ ++ P8_04_pinmux { status = "disabled"; }; /* mmc1_dat7 */ ++}; ++ ++&am33xx_pinmux { ++ emmc_pins: pinmux_emmc_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */ ++ >; ++ }; ++}; ++ ++&mmc2 { ++ vmmc-supply = <&vmmcsd_fixed>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_pins>; ++ bus-width = <8>; ++ status = "okay"; ++ non-removable; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-BONE-LCD4-01-00A1.dtso b/arch/arm/boot/dts/ti/omap/BB-BONE-LCD4-01-00A1.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-BONE-LCD4-01-00A1.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-BONE-LCD4-01-00A1.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,276 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-BONE-LCD4-01-00A1.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_12_pinmux { status = "disabled"; }; /* P9_12: gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */ ++ ++ P9_14_pinmux { status = "disabled"; }; /* P9_14: gpmc_a2.ehrpwm1a */ ++ ++ P9_27_pinmux { status = "disabled"; }; /* P9_27: mcasp0_fsr.gpio3_19 */ ++ ++ P8_45_pinmux { status = "disabled"; }; /* P8_45: lcd_data0.lcd_data0 */ ++ P8_46_pinmux { status = "disabled"; }; /* P8_46: lcd_data1.lcd_data1 */ ++ P8_43_pinmux { status = "disabled"; }; /* P8_43: lcd_data2.lcd_data2 */ ++ P8_44_pinmux { status = "disabled"; }; /* P8_44: lcd_data3.lcd_data3 */ ++ P8_41_pinmux { status = "disabled"; }; /* P8_41: lcd_data4.lcd_data4 */ ++ P8_42_pinmux { status = "disabled"; }; /* P8_42: lcd_data5.lcd_data5 */ ++ P8_39_pinmux { status = "disabled"; }; /* P8_39: lcd_data6.lcd_data6 */ ++ P8_40_pinmux { status = "disabled"; }; /* P8_40: lcd_data7.lcd_data7 */ ++ P8_37_pinmux { status = "disabled"; }; /* P8_37: lcd_data8.lcd_data8 */ ++ P8_38_pinmux { status = "disabled"; }; /* P8_38: lcd_data9.lcd_data9 */ ++ P8_36_pinmux { status = "disabled"; }; /* P8_36: lcd_data10.lcd_data10 */ ++ P8_34_pinmux { status = "disabled"; }; /* P8_34: lcd_data11.lcd_data11 */ ++ P8_35_pinmux { status = "disabled"; }; /* P8_35: lcd_data12.lcd_data12 */ ++ P8_33_pinmux { status = "disabled"; }; /* P8_33: lcd_data13.lcd_data13 */ ++ P8_31_pinmux { status = "disabled"; }; /* P8_31: lcd_data14.lcd_data14 */ ++ P8_32_pinmux { status = "disabled"; }; /* P8_32: lcd_data15.lcd_data15 */ ++ ++ P8_27_pinmux { status = "disabled"; }; /* P8_27: lcd_vsync.lcd_vsync */ ++ P8_29_pinmux { status = "disabled"; }; /* P8_29: lcd_hsync.lcd_hsync */ ++ P8_28_pinmux { status = "disabled"; }; /* P8_28: lcd_pclk.lcd_pclk */ ++ P8_30_pinmux { status = "disabled"; }; /* P8_30: lcd_ac_bias_en.lcd_ac_bias_en */ ++ ++ P9_15_pinmux { status = "disabled"; }; /* P9_15: gpmc_a0.gpio1_16 */ ++ P9_23_pinmux { status = "disabled"; }; /* P9_23: gpmc_a1.gpio1_17 */ ++ P9_16_pinmux { status = "disabled"; }; /* P9_16: gpmc_a3.gpio1_19 */ ++ P9_30_pinmux { status = "disabled"; }; /* P9_30: mcasp0_axr0.gpio3_16 */ ++ P9_24_pinmux { status = "disabled"; }; /* P9_24: uart1_txd.gpio0_15 */ ++}; ++ ++&am33xx_pinmux { ++ bb_lcd_led_pins: pinmux_bb_lcd_led_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT, MUX_MODE7) /* P9_12: gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */ ++ >; ++ }; ++ ++ bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE6) /* P9_14: gpmc_a2.ehrpwm1a */ ++ >; ++ }; ++ ++ bb_lcd_lcd_pins: pinmux_bb_lcd_lcd_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLUP, MUX_MODE7) /* P9_27: mcasp0_fsr.gpio3_19 */ ++ ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0) ++ ++ AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0) ++ >; ++ }; ++ ++ bb_lcd_keymap_pins: pinmux_bb_lcd_keymap_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT, MUX_MODE7) /* P9_15: gpmc_a0.gpio1_16 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT, MUX_MODE7) /* P9_23: gpmc_a1.gpio1_17 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_INPUT, MUX_MODE7) /* P9_16: gpmc_a3.gpio1_19 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT, MUX_MODE7) /* P9_30: mcasp0_axr0.gpio3_16 */ ++ AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE7) /* P9_24: uart1_txd.gpio0_15 */ ++ >; ++ }; ++}; ++ ++&epwmss1 { ++ status = "okay"; ++}; ++ ++&ehrpwm1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_pwm_backlight_pins>; ++ status = "okay"; ++}; ++ ++&lcdc { ++ status = "okay"; ++ ++ blue-and-red-wiring = "straight"; ++ ++ //FIXME - LCD doesn't init... ++ //port { ++ // lcdc_0: endpoint@0 { ++ // remote-endpoint = <&panel_0>; ++ // }; ++ //}; ++}; ++ ++&tscadc { ++ status = "okay"; ++ tsc { ++ ti,wires = <4>; ++ ti,x-plate-resistance = <200>; ++ ti,coordinate-readouts = <5>; ++ ti,wire-config = <0x00 0x11 0x22 0x33>; ++ ti,charge-delay = <0x400>; ++ }; ++ ++ adc { ++ ti,adc-channels = <4 5 6 7>; ++ }; ++}; ++ ++&{/} { ++ backlight: backlight { ++ status = "okay"; ++ compatible = "pwm-backlight"; ++ pwms = <&ehrpwm1 0 500000 0>; ++ brightness-levels = < ++ 0 1 2 3 4 5 6 7 8 9 ++ 10 11 12 13 14 15 16 17 18 19 ++ 20 21 22 23 24 25 26 27 28 29 ++ 30 31 32 33 34 35 36 37 38 39 ++ 40 41 42 43 44 45 46 47 48 49 ++ 50 51 52 53 54 55 56 57 58 59 ++ 60 61 62 63 64 65 66 67 68 69 ++ 70 71 72 73 74 75 76 77 78 79 ++ 80 81 82 83 84 85 86 87 88 89 ++ 90 91 92 93 94 95 96 97 98 99 ++ 100 ++ >; ++ default-brightness-level = <100>; ++ }; ++ ++ panel { ++ status = "okay"; ++ compatible = "ti,tilcdc,panel"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_lcd_pins>; ++ backlight = <&backlight>; ++ ++ //FIXME - LCD doesn't init... ++ //port { ++ // panel_0: endpoint@0 { ++ // remote-endpoint = <&lcdc_0>; ++ // }; ++ //}; ++ ++ panel-info { ++ ac-bias = <255>; ++ ac-bias-intrpt = <0>; ++ dma-burst-sz = <16>; ++ bpp = <16>; ++ fdd = <0x80>; ++ sync-edge = <0>; ++ sync-ctrl = <1>; ++ raster-order = <0>; ++ fifo-th = <0>; ++ }; ++ display-timings { ++ native-mode = <&timing0>; ++ /* www.newhavendisplay.com/app_notes/OTA5180A.pdf */ ++ timing0: 480x272 { ++ clock-frequency = <9200000>; ++ hactive = <480>; ++ vactive = <272>; ++ hfront-porch = <8>; ++ hback-porch = <47>; ++ hsync-len = <41>; ++ vback-porch = <2>; ++ vfront-porch = <3>; ++ vsync-len = <10>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ de-active = <1>; ++ pixelclk-active = <0>; ++ }; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_led_pins>; ++ ++ led-ld0 { ++ label = "lcd:green:usr0"; ++ gpios = <&gpio1 28 0>; ++ linux,default-trigger = "heartbeat"; ++ default-state = "off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_keymap_pins>; ++ ++ button-1 { ++ debounce_interval = <50>; ++ linux,code = <105>; ++ label = "left"; ++ gpios = <&gpio1 16 0x1>; ++ gpio-key,wakeup; ++ autorepeat; ++ }; ++ button-2 { ++ debounce_interval = <50>; ++ linux,code = <106>; ++ label = "right"; ++ gpios = <&gpio1 17 0x1>; ++ gpio-key,wakeup; ++ autorepeat; ++ }; ++ button-3 { ++ debounce_interval = <50>; ++ linux,code = <103>; ++ label = "up"; ++ gpios = <&gpio1 19 0x1>; ++ gpio-key,wakeup; ++ autorepeat; ++ }; ++ button-4 { ++ debounce_interval = <50>; ++ linux,code = <108>; ++ label = "down"; ++ gpios = <&gpio3 16 0x1>; ++ gpio-key,wakeup; ++ autorepeat; ++ }; ++ button-5 { ++ debounce_interval = <50>; ++ linux,code = <28>; ++ label = "enter"; ++ gpios = <&gpio0 15 0x1>; ++ gpio-key,wakeup; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-BONE-NH7C-01-A0.dtso b/arch/arm/boot/dts/ti/omap/BB-BONE-NH7C-01-A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-BONE-NH7C-01-A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-BONE-NH7C-01-A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,232 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-BONE-NH7C-01-A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P8_45_pinmux { status = "disabled"; }; /* lcd: lcd_data0 */ ++ P8_46_pinmux { status = "disabled"; }; /* lcd: lcd_data1 */ ++ P8_43_pinmux { status = "disabled"; }; /* lcd: lcd_data2 */ ++ P8_44_pinmux { status = "disabled"; }; /* lcd: lcd_data3 */ ++ P8_41_pinmux { status = "disabled"; }; /* lcd: lcd_data4 */ ++ P8_42_pinmux { status = "disabled"; }; /* lcd: lcd_data5 */ ++ P8_39_pinmux { status = "disabled"; }; /* lcd: lcd_data6 */ ++ P8_40_pinmux { status = "disabled"; }; /* lcd: lcd_data7 */ ++ P8_37_pinmux { status = "disabled"; }; /* lcd: lcd_data8 */ ++ P8_38_pinmux { status = "disabled"; }; /* lcd: lcd_data9 */ ++ P8_36_pinmux { status = "disabled"; }; /* lcd: lcd_data10 */ ++ P8_34_pinmux { status = "disabled"; }; /* lcd: lcd_data11 */ ++ P8_35_pinmux { status = "disabled"; }; /* lcd: lcd_data12 */ ++ P8_33_pinmux { status = "disabled"; }; /* lcd: lcd_data13 */ ++ P8_31_pinmux { status = "disabled"; }; /* lcd: lcd_data14 */ ++ P8_32_pinmux { status = "disabled"; }; /* lcd: lcd_data15 */ ++ ++ P8_15_pinmux { status = "disabled"; }; /* gpmc_ad15.lcd_data16 */ ++ P8_16_pinmux { status = "disabled"; }; /* gpmc_ad14.lcd_data17 */ ++ P8_11_pinmux { status = "disabled"; }; /* gpmc_ad13.lcd_data18 */ ++ P8_12_pinmux { status = "disabled"; }; /* gpmc_ad12.lcd_data19 */ ++ P8_17_pinmux { status = "disabled"; }; /* gpmc_ad11.lcd_data20 */ ++ P8_14_pinmux { status = "disabled"; }; /* gpmc_ad10.lcd_data21 */ ++ P8_13_pinmux { status = "disabled"; }; /* gpmc_ad9.lcd_data22 */ ++ P8_19_pinmux { status = "disabled"; }; /* gpmc_ad8.lcd_data23 */ ++ ++ P8_27_pinmux { status = "disabled"; }; /* lcd: lcd_vsync */ ++ P8_29_pinmux { status = "disabled"; }; /* lcd: lcd_hsync */ ++ P8_28_pinmux { status = "disabled"; }; /* lcd: lcd_pclk */ ++ P8_30_pinmux { status = "disabled"; }; /* lcd: lcd_ac_bias_en */ ++ ++ P8_18_pinmux { status = "disabled"; }; /* lcd: enable */ ++ ++ P9_14_pinmux { status = "disabled"; }; /* pwm: ehrpwm1a */ ++ ++ P9_27_pinmux { status = "disabled"; }; /* ft5336: gpio3_15 */ ++}; ++ ++&am33xx_pinmux { ++ bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE6) /* P9_14: gpmc_a2.ehrpwm1a */ ++ >; ++ }; ++ ++ bb_lcd_lcd_pins: pinmux_bb_lcd_lcd_pins { ++ pinctrl-single,pins = < ++ /*LCD enable */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_clk_mux0.gpio2_1 */ ++ ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0) ++ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_OUTPUT, MUX_MODE1) /* P8_15: gpmc_ad15.lcd_data16 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_OUTPUT, MUX_MODE1) /* P8_16: gpmc_ad14.lcd_data17 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_OUTPUT, MUX_MODE1) /* P8_11: gpmc_ad13.lcd_data18 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_OUTPUT, MUX_MODE1) /* P8_12: gpmc_ad12.lcd_data19 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE1) /* P8_17: gpmc_ad11.lcd_data20 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE1) /* P8_14: gpmc_ad10.lcd_data21 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE1) /* P8_13: gpmc_ad9.lcd_data22 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1) /* P8_19: gpmc_ad8.lcd_data23 */ ++ ++ AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0) ++ >; ++ }; ++ ++ edt_ft5x06_pins: pinmux_edt_ft5x06_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_INPUT_PULLDOWN, MUX_MODE7) /* mcasp0_fsr.gpio3_19 */ ++ >; ++ }; ++}; ++ ++&epwmss1 { ++ status = "okay"; ++}; ++ ++&ehrpwm1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_pwm_backlight_pins>; ++ status = "okay"; ++}; ++ ++&lcdc { ++ status = "okay"; ++ ++ blue-and-red-wiring = "crossed"; ++ ++ //FIXME - LCD doesn't init... ++ //port { ++ // lcdc_0: endpoint@0 { ++ // remote-endpoint = <&panel_0>; ++ // }; ++ //}; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ edt-ft5x06@38 { ++ status = "okay"; ++ compatible = "edt,edt-ft5406"; ++ reg = <0x38>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&edt_ft5x06_pins>; ++ interrupt-parent = <&gpio3>; ++ interrupts = <19 0>; ++ //reset-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>; ++ ++ touchscreen-size-x = <800>; ++ touchscreen-size-y = <480>; ++ //touchscreen-swapped-x-y; ++ }; ++}; ++ ++&{/} { ++ backlight: backlight { ++ status = "okay"; ++ compatible = "pwm-backlight"; ++ pwms = <&ehrpwm1 0 500000 0>; ++ brightness-levels = < ++ 0 1 2 3 4 5 6 7 8 9 ++ 10 11 12 13 14 15 16 17 18 19 ++ 20 21 22 23 24 25 26 27 28 29 ++ 30 31 32 33 34 35 36 37 38 39 ++ 40 41 42 43 44 45 46 47 48 49 ++ 50 51 52 53 54 55 56 57 58 59 ++ 60 61 62 63 64 65 66 67 68 69 ++ 70 71 72 73 74 75 76 77 78 79 ++ 80 81 82 83 84 85 86 87 88 89 ++ 90 91 92 93 94 95 96 97 98 99 ++ 100 ++ >; ++ default-brightness-level = <100>; ++ }; ++ ++ /* NHD-7.0-800480EF-ATXL# */ ++ panel { ++ status = "okay"; ++ compatible = "ti,tilcdc,panel"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_lcd_pins>; ++ backlight = <&backlight>; ++ enable-gpios = <&gpio2 1 0>; ++ ++ //FIXME - LCD doesn't init... ++ //port { ++ // panel_0: endpoint@0 { ++ // remote-endpoint = <&lcdc_0>; ++ // }; ++ //}; ++ ++ panel-info { ++ ac-bias = <255>; ++ ac-bias-intrpt = <0>; ++ dma-burst-sz = <16>; ++ bpp = <32>; ++ fdd = <0x80>; ++ tft-alt-mode = <0>; ++ stn-565-mode = <0>; ++ mono-8bit-mode = <0>; ++ sync-edge = <0>; ++ sync-ctrl = <0>; ++ raster-order = <0>; ++ fifo-th = <0>; ++ }; ++ ++ display-timings { ++ native-mode = <&timing0>; ++ timing0: 800x480 { ++ clock-frequency = <45000000>; ++ hactive = <800>; ++ vactive = <480>; ++ hfront-porch = <40>; ++ hback-porch = <40>; ++ hsync-len = <48>; ++ vback-porch = <29>; ++ vfront-porch = <13>; ++ vsync-len = <3>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ }; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-CAPE-DISP-CT4-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-CAPE-DISP-CT4-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-CAPE-DISP-CT4-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-CAPE-DISP-CT4-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,210 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-CAPE-DISP-CT4-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P8_45_pinmux { status = "disabled"; }; /* lcd: lcd_data0 */ ++ P8_46_pinmux { status = "disabled"; }; /* lcd: lcd_data1 */ ++ P8_43_pinmux { status = "disabled"; }; /* lcd: lcd_data2 */ ++ P8_44_pinmux { status = "disabled"; }; /* lcd: lcd_data3 */ ++ P8_41_pinmux { status = "disabled"; }; /* lcd: lcd_data4 */ ++ P8_42_pinmux { status = "disabled"; }; /* lcd: lcd_data5 */ ++ P8_39_pinmux { status = "disabled"; }; /* lcd: lcd_data6 */ ++ P8_40_pinmux { status = "disabled"; }; /* lcd: lcd_data7 */ ++ P8_37_pinmux { status = "disabled"; }; /* lcd: lcd_data8 */ ++ P8_38_pinmux { status = "disabled"; }; /* lcd: lcd_data9 */ ++ P8_36_pinmux { status = "disabled"; }; /* lcd: lcd_data10 */ ++ P8_34_pinmux { status = "disabled"; }; /* lcd: lcd_data11 */ ++ P8_35_pinmux { status = "disabled"; }; /* lcd: lcd_data12 */ ++ P8_33_pinmux { status = "disabled"; }; /* lcd: lcd_data13 */ ++ P8_31_pinmux { status = "disabled"; }; /* lcd: lcd_data14 */ ++ P8_32_pinmux { status = "disabled"; }; /* lcd: lcd_data15 */ ++ ++ P8_27_pinmux { status = "disabled"; }; /* lcd: lcd_vsync */ ++ P8_29_pinmux { status = "disabled"; }; /* lcd: lcd_hsync */ ++ P8_28_pinmux { status = "disabled"; }; /* lcd: lcd_pclk */ ++ P8_30_pinmux { status = "disabled"; }; /* lcd: lcd_ac_bias_en */ ++ ++ P9_28_pinmux { status = "disabled"; }; /* pwm: eCAP2_in_PWM2_out */ ++ ++ P9_29_pinmux { status = "disabled"; }; /* ft5336: gpio3_15 */ ++ P9_31_pinmux { status = "disabled"; }; /* ft5336: gpio3_14 */ ++}; ++ ++&am33xx_pinmux { ++ bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE4) /* mcasp0_ahclkr.eCAP2_in_PWM2_out */ ++ >; ++ }; ++ ++ bb_lcd_lcd_pins: pinmux_bb_lcd_lcd_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0) ++ ++ AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0) ++ >; ++ }; ++ ++ edt_ft5336_ts_pins: pinmux_edt_ft5336_ts_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE7) /* mcasp0_fsx.gpio3_15 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLDOWN, MUX_MODE7) /* mcasp0_aclkx.gpio3_14 */ ++ >; ++ }; ++}; ++ ++&epwmss2 { ++ status = "okay"; ++}; ++ ++&ecap2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_pwm_backlight_pins>; ++ status = "okay"; ++}; ++ ++&lcdc { ++ status = "okay"; ++ ++ blue-and-red-wiring = "straight"; ++ ++ //FIXME - LCD doesn't init... ++ //port { ++ // lcdc_0: endpoint@0 { ++ // remote-endpoint = <&panel_0>; ++ // }; ++ //}; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ ++ /* this is the configuration part */ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ edt-ft5336@38 { ++ status = "okay"; ++ compatible = "edt,edt-ft5336", "edt,edt-ft5306", "edt,edt-ft5x06"; ++ reg = <0x38>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&edt_ft5336_ts_pins>; ++ interrupt-parent = <&gpio3>; ++ interrupts = <15 0>; ++ reset-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>; ++ ++ touchscreen-size-x = <272>; ++ touchscreen-size-y = <480>; ++ touchscreen-swapped-x-y; ++ }; ++}; ++ ++&{/} { ++ backlight: backlight { ++ status = "okay"; ++ compatible = "pwm-backlight"; ++ pwms = <&ecap2 0 500000 0>; ++ brightness-levels = < ++ 0 1 2 3 4 5 6 7 8 9 ++ 10 11 12 13 14 15 16 17 18 19 ++ 20 21 22 23 24 25 26 27 28 29 ++ 30 31 32 33 34 35 36 37 38 39 ++ 40 41 42 43 44 45 46 47 48 49 ++ 50 51 52 53 54 55 56 57 58 59 ++ 60 61 62 63 64 65 66 67 68 69 ++ 70 71 72 73 74 75 76 77 78 79 ++ 80 81 82 83 84 85 86 87 88 89 ++ 90 91 92 93 94 95 96 97 98 99 ++ 100 ++ >; ++ default-brightness-level = <50>; ++ }; ++ ++ panel { ++ status = "okay"; ++ compatible = "ti,tilcdc,panel"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_lcd_lcd_pins>; ++ backlight = <&backlight>; ++ ++ //FIXME - LCD doesn't init... ++ //port { ++ // panel_0: endpoint@0 { ++ // remote-endpoint = <&lcdc_0>; ++ // }; ++ //}; ++ ++ panel-info { ++ ac-bias = <255>; ++ ac-bias-intrpt = <0>; ++ dma-burst-sz = <16>; ++ bpp = <16>; ++ fdd = <0x80>; ++ tft-alt-mode = <0>; ++ stn-565-mode = <0>; ++ mono-8bit-mode = <0>; ++ sync-edge = <0>; ++ sync-ctrl = <1>; ++ raster-order = <0>; ++ fifo-th = <0>; ++ }; ++ /* ILI6480 */ ++ display-timings { ++ native-mode = <&timing0>; ++ timing0: 480x272 { ++ clock-frequency = <9000000>; ++ hactive = <480>; ++ vactive = <272>; ++ hfront-porch = <5>; ++ hback-porch = <40>; ++ hsync-len = <1>; ++ vback-porch = <8>; ++ vfront-porch = <8>; ++ vsync-len = <1>; ++ hsync-active = <0>; ++ vsync-active = <0>; ++ }; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-HDMI-TDA998x-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-HDMI-TDA998x-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-HDMI-TDA998x-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-HDMI-TDA998x-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,188 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-HDMI-TDA998x-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_25_pinmux { status = "disabled"; }; /* mcasp0_ahclkx */ ++ P9_28_pinmux { status = "disabled"; }; /* mcasp0_axr2 */ ++ P9_29_pinmux { status = "disabled"; }; /* mcasp0_fsx */ ++ P9_31_pinmux { status = "disabled"; }; /* mcasp0_aclkx */ ++ P8_45_pinmux { status = "disabled"; }; /* lcd_data0 */ ++ P8_46_pinmux { status = "disabled"; }; /* lcd_data1 */ ++ P8_43_pinmux { status = "disabled"; }; /* lcd_data2 */ ++ P8_44_pinmux { status = "disabled"; }; /* lcd_data3 */ ++ P8_41_pinmux { status = "disabled"; }; /* lcd_data4 */ ++ P8_42_pinmux { status = "disabled"; }; /* lcd_data5 */ ++ P8_39_pinmux { status = "disabled"; }; /* lcd_data6 */ ++ P8_40_pinmux { status = "disabled"; }; /* lcd_data7 */ ++ P8_37_pinmux { status = "disabled"; }; /* lcd_data8 */ ++ P8_38_pinmux { status = "disabled"; }; /* lcd_data9 */ ++ P8_36_pinmux { status = "disabled"; }; /* lcd_data10 */ ++ P8_34_pinmux { status = "disabled"; }; /* lcd_data11 */ ++ P8_35_pinmux { status = "disabled"; }; /* lcd_data12 */ ++ P8_33_pinmux { status = "disabled"; }; /* lcd_data13 */ ++ P8_31_pinmux { status = "disabled"; }; /* lcd_data14 */ ++ P8_32_pinmux { status = "disabled"; }; /* lcd_data15 */ ++ P8_27_pinmux { status = "disabled"; }; /* lcd_vsync */ ++ P8_29_pinmux { status = "disabled"; }; /* lcd_hsync */ ++ P8_28_pinmux { status = "disabled"; }; /* lcd_pclk */ ++ P8_30_pinmux { status = "disabled"; }; /* lcd_ac_bias_en */ ++}; ++ ++&am33xx_pinmux { ++ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLUP, MUX_MODE7) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ >; ++ }; ++ ++ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE7) ++ >; ++ }; ++ ++ mcasp0_pins: mcasp0_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLUP, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.GPIO1_27 */ ++ >; ++ }; ++}; ++ ++&lcdc { ++ status = "okay"; ++ ++ /* If you want to get 24 bit RGB and 16 BGR mode instead of ++ * current 16 bit RGB and 24 BGR modes, set the propety ++ * below to "crossed" and uncomment the video-ports -property ++ * in tda19988 node. ++ */ ++ blue-and-red-wiring = "straight"; ++ ++ port { ++ lcdc_0: endpoint@0 { ++ remote-endpoint = <&hdmi_0>; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ tda19988: tda19988@70 { ++ compatible = "nxp,tda998x"; ++ reg = <0x70>; ++ nxp,calib-gpios = <&gpio1 25 0>; ++ interrupts-extended = <&gpio1 25 IRQ_TYPE_LEVEL_LOW>; ++ ++ pinctrl-names = "default", "off"; ++ pinctrl-0 = <&nxp_hdmi_bonelt_pins>; ++ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; ++ ++ /* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */ ++ /* video-ports = <0x234501>; */ ++ ++ #sound-dai-cells = <0>; ++ audio-ports = < TDA998x_I2S 0x03>; ++ ++ ports { ++ port@0 { ++ hdmi_0: endpoint@0 { ++ remote-endpoint = <&lcdc_0>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&mcasp0 { ++ #sound-dai-cells = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcasp0_pins>; ++ status = "okay"; ++ op-mode = <0>; /* MCASP_IIS_MODE */ ++ tdm-slots = <2>; ++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ ++ 0 0 1 0 ++ >; ++ tx-num-evt = <32>; ++ rx-num-evt = <32>; ++}; ++ ++&{/} { ++ clk_mcasp0_fixed: clk_mcasp0_fixed { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <24576000>; ++ }; ++ ++ clk_mcasp0: clk_mcasp0 { ++ #clock-cells = <0>; ++ compatible = "gpio-gate-clock"; ++ clocks = <&clk_mcasp0_fixed>; ++ enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */ ++ }; ++ ++ sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "TI BeagleBone Black"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,bitclock-master = <&dailink0_master>; ++ simple-audio-card,frame-master = <&dailink0_master>; ++ ++ dailink0_master: simple-audio-card,cpu { ++ sound-dai = <&mcasp0>; ++ clocks = <&clk_mcasp0>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&tda19988>; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-I2C1-MCP7940X-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-I2C1-MCP7940X-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-I2C1-MCP7940X-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-I2C1-MCP7940X-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,81 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2015 Robert Nelson ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-I2C1-MCP7940X-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_17_pinmux { status = "disabled"; }; /* spi0_d1.i2c1_sda */ ++ P9_18_pinmux { status = "disabled"; }; /* spi0_cs0.i2c1_scl */ ++ P8_26_pinmux { status = "disabled"; }; /* rtc: gpio1_29 */ ++}; ++ ++&{/} { ++ aliases { ++ rtc0 = &extrtc; ++ /* find /sys/firmware/devicetree/ | grep rtc@ */ ++ rtc1 = "/ocp/interconnect@44c00000/segment@200000/target-module@3e000/rtc@0"; ++ }; ++ ++ gpio_keys { ++ compatible = "gpio-keys"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_gpio1_29_pins>; ++ ++ rtc_mfp@1 { ++ label = "rtc_mfp"; ++ gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>; ++ linux,code = <143>; /* System Wake Up */ ++ gpio-key,wakeup; ++ }; ++ }; ++}; ++ ++&am33xx_pinmux { ++ bb_gpio1_29_pins: pinmux_bb_gpio1_29_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_INPUT, MUX_MODE7) /* gpmc_csn0.gpio1_29 */ ++ >; ++ }; ++ ++ bb_i2c1_pins: pinmux_bb_i2c1_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_SPI0_D1, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d1.i2c1_sda */ ++ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_cs0.i2c1_scl */ ++ >; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_i2c1_pins>; ++ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ extrtc: mcp7940x@68 { ++ status = "okay"; ++ compatible = "microchip,mcp7940x"; ++ reg = <0x68>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-I2C1-RTC-DS3231.dtso b/arch/arm/boot/dts/ti/omap/BB-I2C1-RTC-DS3231.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-I2C1-RTC-DS3231.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-I2C1-RTC-DS3231.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,69 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2021 Sam Cohen ++ * ++ * Based on BB-I2C2-RTC-DS3231.dts: ++ * Copyright (C) 2019 Tomas Arturo Herrera Castro ++ * ++ * DTS file for DS3231 Real Time Clock, running on the I2C1 interface. Also see ++ * BB-I2C2-RTC-DS3231.dts to run this RTC on I2C2. ++ * ++ * Tested on BeagleBone Black Wireless ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-I2C1-RTC-DS3231.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_17_pinmux { status = "disabled"; }; /* spi0_d1.i2c1_sda */ ++ P9_18_pinmux { status = "disabled"; }; /* spi0_cs0.i2c1_scl */ ++}; ++ ++&{/} { ++ aliases { ++ rtc0 = &extrtc; ++ /* find /sys/firmware/devicetree/ | grep rtc@ */ ++ rtc1 = "/ocp/interconnect@44c00000/segment@200000/target-module@3e000/rtc@0"; ++ }; ++}; ++ ++&am33xx_pinmux { ++ bb_i2c1_pins: pinmux_bb_i2c1_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_SPI0_D1, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d1.i2c1_sda */ ++ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_cs0.i2c1_scl */ ++ >; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_i2c1_pins>; ++ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ extrtc: ds3231@68 { ++ status = "okay"; ++ compatible = "maxim,ds3231"; ++ reg = <0x68>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-I2C1-RTC-PCF8563.dtso b/arch/arm/boot/dts/ti/omap/BB-I2C1-RTC-PCF8563.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-I2C1-RTC-PCF8563.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-I2C1-RTC-PCF8563.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,61 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2018 Robert Nelson ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-I2C1-RTC-PCF8563.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_17_pinmux { status = "disabled"; }; /* spi0_d1.i2c1_sda */ ++ P9_18_pinmux { status = "disabled"; }; /* spi0_cs0.i2c1_scl */ ++}; ++ ++&{/} { ++ aliases { ++ rtc0 = &extrtc; ++ /* find /sys/firmware/devicetree/ | grep rtc@ */ ++ rtc1 = "/ocp/interconnect@44c00000/segment@200000/target-module@3e000/rtc@0"; ++ }; ++}; ++ ++&am33xx_pinmux { ++ bb_i2c1_pins: pinmux_bb_i2c1_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_SPI0_D1, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_d1.i2c1_sda */ ++ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2) /* spi0_cs0.i2c1_scl */ ++ >; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_i2c1_pins>; ++ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ extrtc: pcf8563@51 { ++ status = "okay"; ++ compatible = "nxp,pcf8563"; ++ reg = <0x51>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-I2C2-BME680.dtso b/arch/arm/boot/dts/ti/omap/BB-I2C2-BME680.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-I2C2-BME680.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-I2C2-BME680.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,31 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2022 Robert Nelson ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-I2C2-BME680.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ ++ clock-frequency = <100000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ bme680@76 { ++ status = "okay"; ++ compatible = "bosch,bme680"; ++ reg = <0x76>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-I2C2-MPU6050.dtso b/arch/arm/boot/dts/ti/omap/BB-I2C2-MPU6050.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-I2C2-MPU6050.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-I2C2-MPU6050.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,53 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2022 Robert Nelson ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-I2C2-MPU6050.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_12_pinmux { status = "disabled"; }; ++}; ++ ++&am33xx_pinmux { ++ mpu6050_pins: pinmux_mpu6050_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT, MUX_MODE7) /* gpio1_28 */ ++ >; ++ }; ++}; ++ ++&i2c2 { ++ status = "okay"; ++ ++ clock-frequency = <400000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ imu@68 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mpu6050_pins>; ++ compatible = "invensense,mpu6050"; ++ reg = <0x68>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <28 IRQ_TYPE_EDGE_RISING>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-LCD-ADAFRUIT-24-SPI1-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-LCD-ADAFRUIT-24-SPI1-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-LCD-ADAFRUIT-24-SPI1-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-LCD-ADAFRUIT-24-SPI1-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,180 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 CircuitCo ++ * Copyright (C) 2018 Drew Fustini ++ * Copyright (C) 2019 Mark A. Yoder ++ * ++ * Adafruit 2.4" TFT LCD on SPI1 bus using tinydrm ili9341 driver ++ * ++ * DOCUMENTATION: ++ * -------------- ++ * This file was copied from src/arm/BB-SPIDEV1-00A0.dts and modified ++ * by Drew Fustini based on an exmample from David Lechner. ++ * Later modified by Mark A. Yoder for the 2.4" LCD. ++ * ++ * This is the Adafruit 2.4" TFT LCD: ++ * https://www.adafruit.com/product/2478 ++ * ++ * It should be connected to BeagleBone SPI1 bus: ++ * ++ * P9.16 <--> lite (pwm) [OPTIONAL] ++ * P9.23 <--> lite (gpio) [OPTIONAL] ++ * P9.25 <--> reset ++ * P9.27 <--> dc ++ * P9.28 <--> tft_cs ++ * P9.29 <--> miso ++ * P9.30 <--> mosi ++ * P9.31 <--> clk ++ * ++ * This overlay will load the mainline tinydrm ili9341 driver by David Lechner: ++ * https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/tiny/ili9341.c ++ * ++ * Tested with 4.19.59-ti-r26 kernel on Debian 10.1 image ++ * ++ * Run libdrm modetest for colorbar test based on instructions from: ++ * https://github.com/notro/tinydrm/wiki/Development#modetest ++ * ++ * modetest -M "ili9341" -c #this will display connector id ++ * modetest -M "ili9341" -s 28:128x160 #connector id and resolution ++ * # you should now see a color bar on the LCD ++ * ++ * Mailing list post with more information: ++ * https://groups.google.com/d/msg/beagleboard/GuMQIP_XCW0/b3lxbx_8AwAJ ++ * ++ * Discussion with notro on how to test tinydrm driver: ++ * https://github.com/notro/tinydrm/issues/1#issuecomment-367279037 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-LCD-ADAFRUIT-24-SPI1-00A0 = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_25_pinmux { status = "disabled"; }; /* lcd reset */ ++ P9_16_pinmux { status = "disabled"; }; /* lcd pwm backlight (OPTIONAL) */ ++ P9_27_pinmux { status = "disabled"; }; /* lcd dc */ ++ P9_28_pinmux { status = "disabled"; }; /* spi1_cs0 */ ++ P9_29_pinmux { status = "disabled"; }; /* spi1_d0 */ ++ P9_30_pinmux { status = "disabled"; }; /* spi1_d1 */ ++ P9_31_pinmux { status = "disabled"; }; /* spi1_sclk */ ++}; ++ ++&am33xx_pinmux { ++ /* default state has all gpios released and mode set to uart1 */ ++ /* See page 1446 of am35xx TRM */ ++ bb_spi1_pins: pinmux_bb_spi1_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT, MUX_MODE3) /* mcasp0_aclkx.spi1_sclk */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT, MUX_MODE3) /* mcasp0_fsx.spi1_d0 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT, MUX_MODE3) /* mcasp0_axr0.spi1_d1 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_INPUT, MUX_MODE3) /* mcasp0_ahclkr.spi1_cs0 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpio, dc */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpio, reset */ ++ >; ++ }; ++ ++ backlight_pwm_pins: pinmux_backlight_pwm_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT, MUX_MODE6) /* gpmc_a2.ehrpwm1b */ ++ >; ++ }; /* gpmc_a2.ehrpwm1b */ ++}; ++ ++&epwmss1 { ++ status = "okay"; ++}; ++ ++&ehrpwm1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&backlight_pwm_pins>; ++ status = "okay"; ++}; ++ ++&spi1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_spi1_pins>; ++ ++ channel@0{ ++ status = "disabled"; ++ reg = <0>; ++ }; ++ ++ display@0{ ++ status = "okay"; ++ compatible = "adafruit,yx240qv29", "ilitek,ili9341"; ++ reg = <0>; ++ spi-max-frequency = <32000000>; ++ dc-gpios = <&gpio3 19 0>; // lcd dc P9.27 gpio3[19] ++ reset-gpios = <&gpio3 21 0>; // lcd reset P9.25 gpio3[21] ++ // backlight is optional ++ // choose either pwm or gpio control ++ //backlight = <&backlight_gpio>; // lcd lite P9.23 gpio1[17] ++ backlight = <&backlight_pwm>; // lcd lite P9.16 gpmc_a2.ehrpwm1b ++ // refer to https://elinux.org/Beagleboard:Cape_Expansion_Headers ++ // rotation is optional ++ rotation = <270>; ++ }; ++}; ++ ++&{/} { ++ bl_reg: backlight-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "backlight"; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ /* backlight is optional */ ++ backlight_gpio: backlight_gpio { ++ compatible = "gpio-backlight"; ++ gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>; ++ // connect lcd lite pin to P9.23 which is gpio1[17] ++ // refer to https://elinux.org/Beagleboard:Cape_Expansion_Headers ++ }; ++ ++ /* ++ * Turn the PWM backlight on by setting bl_power to 0: ++ * echo 0 > /sys/class/backlight/backlight_pwm/bl_power ++ */ ++ backlight_pwm: backlight_pwm { ++ // P9.16 <--> lite (pwm-backlight EHRPWM1B) ++ status = "okay"; ++ compatible = "pwm-backlight"; ++ pwms = <&ehrpwm1 1 500000 0>; // First digit: 0 for A side of pwm, 1 for B side ++ // 500000 is the PWM period in ns ++ // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/pwm/pwm.txt ++ brightness-levels = < ++ 0 1 2 3 4 5 6 7 8 9 ++ 10 11 12 13 14 15 16 17 18 19 ++ 20 21 22 23 24 25 26 27 28 29 ++ 30 31 32 33 34 35 36 37 38 39 ++ 40 41 42 43 44 45 46 47 48 49 ++ 50 51 52 53 54 55 56 57 58 59 ++ 60 61 62 63 64 65 66 67 68 69 ++ 70 71 72 73 74 75 76 77 78 79 ++ 80 81 82 83 84 85 86 87 88 89 ++ 90 91 92 93 94 95 96 97 98 99 ++ 100 ++ >; ++ default-brightness-level = <100>; ++ power-supply = <&bl_reg>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-NHDMI-TDA998x-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-NHDMI-TDA998x-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-NHDMI-TDA998x-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-NHDMI-TDA998x-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,125 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-NHDMI-TDA998x-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P8_45_pinmux { status = "disabled"; }; /* lcd_data0 */ ++ P8_46_pinmux { status = "disabled"; }; /* lcd_data1 */ ++ P8_43_pinmux { status = "disabled"; }; /* lcd_data2 */ ++ P8_44_pinmux { status = "disabled"; }; /* lcd_data3 */ ++ P8_41_pinmux { status = "disabled"; }; /* lcd_data4 */ ++ P8_42_pinmux { status = "disabled"; }; /* lcd_data5 */ ++ P8_39_pinmux { status = "disabled"; }; /* lcd_data6 */ ++ P8_40_pinmux { status = "disabled"; }; /* lcd_data7 */ ++ P8_37_pinmux { status = "disabled"; }; /* lcd_data8 */ ++ P8_38_pinmux { status = "disabled"; }; /* lcd_data9 */ ++ P8_36_pinmux { status = "disabled"; }; /* lcd_data10 */ ++ P8_34_pinmux { status = "disabled"; }; /* lcd_data11 */ ++ P8_35_pinmux { status = "disabled"; }; /* lcd_data12 */ ++ P8_33_pinmux { status = "disabled"; }; /* lcd_data13 */ ++ P8_31_pinmux { status = "disabled"; }; /* lcd_data14 */ ++ P8_32_pinmux { status = "disabled"; }; /* lcd_data15 */ ++ P8_27_pinmux { status = "disabled"; }; /* lcd_vsync */ ++ P8_29_pinmux { status = "disabled"; }; /* lcd_hsync */ ++ P8_28_pinmux { status = "disabled"; }; /* lcd_pclk */ ++ P8_30_pinmux { status = "disabled"; }; /* lcd_ac_bias_en */ ++}; ++ ++&am33xx_pinmux { ++ nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLUP, MUX_MODE7) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0) ++ >; ++ }; ++ ++ nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE7) ++ >; ++ }; ++}; ++ ++&lcdc { ++ status = "okay"; ++ ++ /* If you want to get 24 bit RGB and 16 BGR mode instead of ++ * current 16 bit RGB and 24 BGR modes, set the propety ++ * below to "crossed" and uncomment the video-ports -property ++ * in tda19988 node. ++ */ ++ blue-and-red-wiring = "straight"; ++ ++ port { ++ lcdc_0: endpoint@0 { ++ remote-endpoint = <&hdmi_0>; ++ }; ++ }; ++}; ++ ++&i2c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ tda19988: tda19988@70 { ++ compatible = "nxp,tda998x"; ++ reg = <0x70>; ++ nxp,calib-gpios = <&gpio1 25 0>; ++ interrupts-extended = <&gpio1 25 IRQ_TYPE_LEVEL_LOW>; ++ ++ pinctrl-names = "default", "off"; ++ pinctrl-0 = <&nxp_hdmi_bonelt_pins>; ++ pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; ++ ++ /* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */ ++ /* video-ports = <0x234501>; */ ++ ++ ports { ++ port@0 { ++ hdmi_0: endpoint@0 { ++ remote-endpoint = <&lcdc_0>; ++ }; ++ }; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BBORG_COMMS-00A2.dtso b/arch/arm/boot/dts/ti/omap/BBORG_COMMS-00A2.dtso +--- a/arch/arm/boot/dts/ti/omap/BBORG_COMMS-00A2.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BBORG_COMMS-00A2.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,48 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012,2019 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2015 Robert Nelson ++ * Copyright (C) 2015 Sebastian JegerÃ¥s ++ */ ++ ++/* ++ * Tested RobertCNelson [20240119] BBB and BBAI (6.1.69-ti-r21) ++ * ++ * sudo ip link set can0 type can bitrate 500000 ++ * sudo ifconfig can0 up ++ * ++ * candump can0 ++ * cansend can0 123#DEADBEEF ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BBORG_COMMS-00A2.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_24_pinmux { status = "disabled"; }; ++ P9_26_pinmux { status = "disabled"; }; ++ P9_13_pinmux { status = "disabled"; }; ++ P9_11_pinmux { status = "disabled"; }; ++}; ++ ++&bone_can_1 { ++ status = "okay"; ++}; ++ ++&bone_uart_4 { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BBORG_FAN-A000.dtso b/arch/arm/boot/dts/ti/omap/BBORG_FAN-A000.dtso +--- a/arch/arm/boot/dts/ti/omap/BBORG_FAN-A000.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BBORG_FAN-A000.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 Robert Nelson ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BBORG_FAN-A000.kernel = __TIMESTAMP__; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BBORG_RELAY-00A2.dtso b/arch/arm/boot/dts/ti/omap/BBORG_RELAY-00A2.dtso +--- a/arch/arm/boot/dts/ti/omap/BBORG_RELAY-00A2.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BBORG_RELAY-00A2.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2015 Robert Nelson ++ * Copyright (C) 2019 Amilcar Lucas ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BBORG_RELAY-00A2.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_41_pinmux { status = "disabled"; }; /* P9_41: gpmc_a0.gpio0_20 */ ++ P9_42_pinmux { status = "disabled"; }; /* P9_42: gpmc_a1.gpio0_07 */ ++ P9_30_pinmux { status = "disabled"; }; /* P9_30: gpmc_be1n.gpio3_16 */ ++ P9_27_pinmux { status = "disabled"; }; /* P9_27: mcasp0_fsr.gpio3_19 */ ++}; ++ ++&am33xx_pinmux { ++ bb_gpio_relay_pins: pinmux_bb_gpio_relay_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* P9_41: Relay1 */ ++ AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* P9_42: Relay2 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* P9_30: Relay3 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* P9_27: Relay4 */ ++ >; ++ }; ++}; ++ ++&{/} { ++ leds { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_gpio_relay_pins>; ++ ++ compatible = "gpio-leds"; ++ ++ jp@1 { ++ label = "relay-jp1"; ++ gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; ++ default-state = "keep"; ++ }; ++ ++ jp@2 { ++ label = "relay-jp2"; ++ gpios = <&gpio0 07 GPIO_ACTIVE_HIGH>; ++ default-state = "keep"; ++ }; ++ ++ jp@3 { ++ label = "relay-jp3"; ++ gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; ++ default-state = "keep"; ++ }; ++ ++ jp@4 { ++ label = "relay-jp4"; ++ gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; ++ default-state = "keep"; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-SPIDEV0-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-SPIDEV0-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-SPIDEV0-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-SPIDEV0-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,81 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 CircuitCo ++ * Virtual cape for SPI0 on connector pins P9.22 P9.21 P9.18 P9.17 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-SPIDEV0-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_17_pinmux { status = "disabled"; }; /* P9_17 (A16) spi0_cs0.spi0_cs0 */ ++ P9_18_pinmux { status = "disabled"; }; /* P9_18 (B16) spi0_d1.spi0_d1 */ ++ P9_21_pinmux { status = "disabled"; }; /* P9_21 (B17) spi0_d0.spi0_d0 */ ++ P9_22_pinmux { status = "disabled"; }; /* P9_22 (A17) spi0_sclk.spi0_sclk */ ++}; ++ ++&am33xx_pinmux { ++ bb_spi0_pins: pinmux_bb_spi0_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE0) /* P9_22 (A17) spi0_sclk.spi0_sclk */ ++ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT, MUX_MODE0) /* P9_21 (B17) spi0_d0.spi0_d0 */ ++ AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT, MUX_MODE0) /* P9_18 (B16) spi0_d1.spi0_d1 */ ++ AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT, MUX_MODE0) /* P9_17 (A16) spi0_cs0.spi0_cs0 */ ++ >; ++ }; ++}; ++ ++&spi0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_spi0_pins>; ++ ++ /* ++ * Select the D0 pin as output and D1 as ++ * input. The default is D0 as input and ++ * D1 as output. ++ */ ++ //ti,pindir-d0-out-d1-in; ++ ++ channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/0.0"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/0.1"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-SPIDEV1-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-SPIDEV1-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-SPIDEV1-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-SPIDEV1-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,81 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 CircuitCo ++ * Virtual cape for SPI1 on connector pins P9.29 P9.31 P9.30 P9.28 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-SPIDEV1-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_28_pinmux { status = "disabled"; }; /* P9_28 (C12) mcasp0_ahclkr.spi1_cs0 */ ++ P9_30_pinmux { status = "disabled"; }; /* P9_30 (D12) mcasp0_axr0.spi1_d1 */ ++ P9_29_pinmux { status = "disabled"; }; /* P9_29 (B13) mcasp0_fsx.spi1_d0 */ ++ P9_31_pinmux { status = "disabled"; }; /* P9_31 (A13) mcasp0_aclkx.spi1_sclk */ ++}; ++ ++&am33xx_pinmux { ++ bb_spi1_pins: pinmux_bb_spi1_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT, MUX_MODE3) /* P9_31 (A13) mcasp0_aclkx.spi1_sclk */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT, MUX_MODE3) /* P9_29 (B13) mcasp0_fsx.spi1_d0 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT, MUX_MODE3) /* P9_30 (D12) mcasp0_axr0.spi1_d1 */ ++ AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_INPUT, MUX_MODE3) /* P9_28 (C12) mcasp0_ahclkr.spi1_cs0 */ ++ >; ++ }; ++}; ++ ++&spi1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_spi1_pins>; ++ ++ /* ++ * Select the D0 pin as output and D1 as ++ * input. The default is D0 as input and ++ * D1 as output. ++ */ ++ //ti,pindir-d0-out-d1-in; ++ ++ channel@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/1.0"; ++ ++ reg = <0>; ++ spi-max-frequency = <16000000>; ++ spi-cpha; ++ }; ++ ++ channel@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ compatible = "rohm,dh2228fv"; ++ symlink = "bone/spi/1.1"; ++ ++ reg = <1>; ++ spi-max-frequency = <16000000>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-UART1-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-UART1-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-UART1-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-UART1-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,45 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 CircuitCo ++ * Virtual cape for UART1 on connector pins P9.24 P9.26 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-UART1-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_24_pinmux { status = "disabled"; }; /* uart1_txd */ ++ P9_26_pinmux { status = "disabled"; }; /* uart1_rxd */ ++}; ++ ++&am33xx_pinmux { ++ bb_uart1_pins: pinmux_bb_uart1_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT, MUX_MODE0) /* P9_24 uart1_txd.uart1_txd */ ++ AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0) /* P9_26 uart1_rxd.uart1_rxd */ ++ //AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT, MUX_MODE0) /* P9_19 uart1_rtsn.uart1_rtsn */ ++ //AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0) /* P9_20 uart1_ctsn.uart1_ctsn */ ++ >; ++ }; ++}; ++ ++&uart1 { ++ /* sudo agetty 115200 ttyS1 */ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_uart1_pins>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-UART2-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-UART2-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-UART2-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-UART2-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,45 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 CircuitCo ++ * Virtual cape for UART2 on connector pins P9.21 P9.22 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-UART2-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_21_pinmux { status = "disabled"; }; /* P9_21: spi0_d0.uart2_txd */ ++ P9_22_pinmux { status = "disabled"; }; /* P9_22: spi0_sclk.uart2_rxd */ ++}; ++ ++&am33xx_pinmux { ++ bb_uart2_pins: pinmux_bb_uart2_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1) /* P9_21 spi0_d0.uart2_txd */ ++ AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1) /* P9_22 spi0_sclk.uart2_rxd */ ++ //AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE6) /* P8_38 lcd_data9.uart2_rtsn */ ++ //AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_INPUT, MUX_MODE6) /* P8_37 lcd_data8.uart2_ctsn */ ++ >; ++ }; ++}; ++ ++&uart2 { ++ /* sudo agetty 115200 ttyS2 */ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_uart2_pins>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-UART4-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-UART4-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-UART4-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-UART4-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,43 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2013 CircuitCo ++ * Virtual cape for UART4 on connector pins P9.13 P9.11 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-UART4-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_13_pinmux { status = "disabled"; }; /* P9_13: uart4_txd */ ++ P9_11_pinmux { status = "disabled"; }; /* P9_11: uart4_rxd */ ++}; ++ ++&am33xx_pinmux { ++ bb_uart4_pins: pinmux_bb_uart4_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT, MUX_MODE6) /* P9_13 gpmc_wpn.uart4_txd_mux2 */ ++ AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT, MUX_MODE6) /* P9_13 gpmc_wait0.uart4_rxd_mux2 */ ++ >; ++ }; ++}; ++ ++&uart4 { ++ /* sudo agetty 115200 ttyS4 */ ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_uart4_pins>; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BB-W1-P9.12-00A0.dtso b/arch/arm/boot/dts/ti/omap/BB-W1-P9.12-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/BB-W1-P9.12-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BB-W1-P9.12-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,46 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2015 Robert Nelson ++ * Virtual cape for onewire on connector pin P9.12 ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BB-W1-P9.12-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P9_12_pinmux { status = "disabled"; }; /* P9_12 (U18) gpmc_be1n.gpio1_28 */ ++}; ++ ++&am33xx_pinmux { ++ bb_dallas_w1_pins: pinmux_bb_dallas_w1_pins { ++ pinctrl-single,pins = < ++ AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLUP, MUX_MODE7) /* P9_12 (U18) gpmc_be1n.gpio1_28 */ ++ >; ++ }; ++}; ++ ++&{/} { ++ onewire { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&bb_dallas_w1_pins>; ++ ++ compatible = "w1-gpio"; ++ gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/BONE-ADC.dtso b/arch/arm/boot/dts/ti/omap/BONE-ADC.dtso +--- a/arch/arm/boot/dts/ti/omap/BONE-ADC.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/BONE-ADC.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,28 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 Deepak Khatri ++ * See Cape Interface Spec page for more info on Bone Buses ++ * https://elinux.org/Beagleboard:BeagleBone_cape_interface_spec ++ * ++ * Virtual cape for Bone ADC ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ BONE-ADC.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * See these files for the phandles (&bone_*) and other bone bus nodes ++ * am335x-bbb-bone-buses.dtsi ++ */ ++&bone_adc { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/dra7.dtsi b/arch/arm/boot/dts/ti/omap/dra7.dtsi +--- a/arch/arm/boot/dts/ti/omap/dra7.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -638,7 +638,7 @@ + }; + }; + +- abb_mpu: regulator-abb-mpu { ++ abb_mpu: regulator-abb-mpu@4ae07ddc { + compatible = "ti,abb-v3"; + regulator-name = "abb_mpu"; + #address-cells = <0>; +@@ -671,7 +671,7 @@ + >; + }; + +- abb_ivahd: regulator-abb-ivahd { ++ abb_ivahd: regulator-abb-ivahd@4ae07e34 { + compatible = "ti,abb-v3"; + regulator-name = "abb_ivahd"; + #address-cells = <0>; +@@ -704,7 +704,7 @@ + >; + }; + +- abb_dspeve: regulator-abb-dspeve { ++ abb_dspeve: regulator-abb-dspeve@4ae07e30 { + compatible = "ti,abb-v3"; + regulator-name = "abb_dspeve"; + #address-cells = <0>; +@@ -737,7 +737,7 @@ + >; + }; + +- abb_gpu: regulator-abb-gpu { ++ abb_gpu: regulator-abb-gpu@4ae07de4 { + compatible = "ti,abb-v3"; + regulator-name = "abb_gpu"; + #address-cells = <0>; +@@ -850,12 +850,19 @@ + ; + ti,sysc-sidle = , + , +- ; ++ , ++ ; + clocks = <&gpu_clkctrl DRA7_GPU_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x56000000 0x2000000>; ++ ++ gpu@0 { ++ compatible = "ti,am5728-gpu", "img,powervr-sgx544"; ++ reg = <0x0 0x10000>; /* 64kB */ ++ interrupts = ; ++ }; + }; + + crossbar_mpu: crossbar@4a002a48 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/dra7-l4.dtsi b/arch/arm/boot/dts/ti/omap/dra7-l4.dtsi +--- a/arch/arm/boot/dts/ti/omap/dra7-l4.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/dra7-l4.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -80,7 +80,7 @@ + }; + }; + +- phy_gmii_sel: phy-gmii-sel { ++ phy_gmii_sel: phy-gmii-sel@554 { + compatible = "ti,dra7xx-phy-gmii-sel"; + reg = <0x554 0x4>; + #phy-cells = <1>; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi b/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi +--- a/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/dra7xx-clocks.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1685,7 +1685,7 @@ + reg = <0x0558>; + }; + +- sys_32k_ck: clock-sys-32k { ++ sys_32k_ck: clock-sys-32k@6c4 { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clock-output-names = "sys_32k_ck"; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/Makefile b/arch/arm/boot/dts/ti/omap/Makefile +--- a/arch/arm/boot/dts/ti/omap/Makefile 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/Makefile 2024-03-28 11:26:09.893017428 -0400 +@@ -1,4 +1,9 @@ + # SPDX-License-Identifier: GPL-2.0 ++ ++ifeq ($(CONFIG_OF_OVERLAY),y) ++DTC_FLAGS += -@ ++endif ++ + dtb-$(CONFIG_ARCH_OMAP2) += \ + omap2420-h4.dtb \ + omap2420-n800.dtb \ +@@ -87,6 +92,39 @@ + am335x-base0033.dtb \ + am335x-bone.dtb \ + am335x-boneblack.dtb \ ++ am335x-boneblack-uboot.dtb \ ++ PB-MIKROBUS-1.dtbo \ ++ PB-MIKROBUS-0.dtbo \ ++ M-BB-BBGG-00A0.dtbo \ ++ M-BB-BBG-00A0.dtbo \ ++ BONE-ADC.dtbo \ ++ BBORG_RELAY-00A2.dtbo \ ++ BBORG_FAN-A000.dtbo \ ++ BBORG_COMMS-00A2.dtbo \ ++ BB-W1-P9.12-00A0.dtbo \ ++ BB-UART4-00A0.dtbo \ ++ BB-UART2-00A0.dtbo \ ++ BB-UART1-00A0.dtbo \ ++ BB-SPIDEV1-00A0.dtbo \ ++ BB-SPIDEV0-00A0.dtbo \ ++ BB-NHDMI-TDA998x-00A0.dtbo \ ++ BB-LCD-ADAFRUIT-24-SPI1-00A0.dtbo \ ++ BB-I2C2-MPU6050.dtbo \ ++ BB-I2C2-BME680.dtbo \ ++ BB-I2C1-RTC-PCF8563.dtbo \ ++ BB-I2C1-RTC-DS3231.dtbo \ ++ BB-I2C1-MCP7940X-00A0.dtbo \ ++ BB-HDMI-TDA998x-00A0.dtbo \ ++ BB-CAPE-DISP-CT4-00A0.dtbo \ ++ BB-BONE-eMMC1-01-00A0.dtbo \ ++ BB-BONE-NH7C-01-A0.dtbo \ ++ BB-BONE-LCD4-01-00A1.dtbo \ ++ BB-BONE-4D5R-01-00A1.dtbo \ ++ BB-BBGW-WL1835-00A0.dtbo \ ++ BB-BBGG-WL1835-00A0.dtbo \ ++ BB-BBBW-WL1835-00A0.dtbo \ ++ BB-ADC-00A0.dtbo \ ++ AM335X-PRU-UIO-00A0.dtbo \ + am335x-boneblack-wireless.dtb \ + am335x-boneblue.dtb \ + am335x-bonegreen.dtb \ +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/M-BB-BBG-00A0.dtso b/arch/arm/boot/dts/ti/omap/M-BB-BBG-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/M-BB-BBG-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/M-BB-BBG-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ M-BB-BBG-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++&{/} { ++ model = "TI AM335x BeagleBone Green"; ++ compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/M-BB-BBGG-00A0.dtso b/arch/arm/boot/dts/ti/omap/M-BB-BBGG-00A0.dtso +--- a/arch/arm/boot/dts/ti/omap/M-BB-BBGG-00A0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/M-BB-BBGG-00A0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ M-BB-BBGG-00A0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++&{/} { ++ model = "SeeedStudio BeagleBone Green Gateway"; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/omap34xx.dtsi b/arch/arm/boot/dts/ti/omap/omap34xx.dtsi +--- a/arch/arm/boot/dts/ti/omap/omap34xx.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/omap34xx.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -164,12 +164,13 @@ + clock-names = "fck", "ick"; + #address-cells = <1>; + #size-cells = <1>; +- ranges = <0 0x50000000 0x4000>; ++ ranges = <0 0x50000000 0x10000>; + +- /* +- * Closed source PowerVR driver, no child device +- * binding or driver in mainline +- */ ++ gpu@0 { ++ compatible = "ti,omap3430-gpu", "img,powervr-sgx530"; ++ reg = <0x0 0x10000>; /* 64kB */ ++ interrupts = <21>; ++ }; + }; + }; + +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/omap36xx.dtsi b/arch/arm/boot/dts/ti/omap/omap36xx.dtsi +--- a/arch/arm/boot/dts/ti/omap/omap36xx.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/omap36xx.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -211,10 +211,11 @@ + #size-cells = <1>; + ranges = <0 0x50000000 0x2000000>; + +- /* +- * Closed source PowerVR driver, no child device +- * binding or driver in mainline +- */ ++ gpu@0 { ++ compatible = "ti,omap3630-gpu", "img,powervr-sgx530"; ++ reg = <0x0 0x2000000>; /* 32MB */ ++ interrupts = <21>; ++ }; + }; + }; + +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/omap4.dtsi b/arch/arm/boot/dts/ti/omap/omap4.dtsi +--- a/arch/arm/boot/dts/ti/omap/omap4.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/omap4.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -501,10 +501,11 @@ + #size-cells = <1>; + ranges = <0 0x56000000 0x2000000>; + +- /* +- * Closed source PowerVR driver, no child device +- * binding or driver in mainline +- */ ++ gpu@0 { ++ compatible = "ti,omap4430-gpu", "img,powervr-sgx540"; ++ reg = <0x0 0x2000000>; /* 32MB */ ++ interrupts = ; ++ }; + }; + + /* +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/omap4-panda-common.dtsi b/arch/arm/boot/dts/ti/omap/omap4-panda-common.dtsi +--- a/arch/arm/boot/dts/ti/omap/omap4-panda-common.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/omap4-panda-common.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -408,6 +408,7 @@ + reg = <0x48>; + /* IRQ# = 7 */ + interrupts = ; /* IRQ_SYS_1N cascaded to gic */ ++ system-power-controller; + }; + + twl6040: twl@4b { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/omap4-sdp.dts b/arch/arm/boot/dts/ti/omap/omap4-sdp.dts +--- a/arch/arm/boot/dts/ti/omap/omap4-sdp.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/omap4-sdp.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -439,7 +439,7 @@ + + /* + * Ambient Light Sensor +- * http://www.rohm.com/products/databook/sensor/pdf/bh1780gli-e.pdf ++ * https://www.rohm.com/products/databook/sensor/pdf/bh1780gli-e.pdf (defunct) + */ + bh1780@29 { + compatible = "rohm,bh1780"; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/omap5.dtsi b/arch/arm/boot/dts/ti/omap/omap5.dtsi +--- a/arch/arm/boot/dts/ti/omap/omap5.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/omap5.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -453,10 +453,11 @@ + #size-cells = <1>; + ranges = <0 0x56000000 0x2000000>; + +- /* +- * Closed source PowerVR driver, no child device +- * binding or driver in mainline +- */ ++ gpu@0 { ++ compatible = "ti,omap5432-gpu", "img,powervr-sgx544"; ++ reg = <0x0 0x2000000>; /* 32MB */ ++ interrupts = ; ++ }; + }; + + target-module@58000000 { +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/PB-MIKROBUS-0.dtso b/arch/arm/boot/dts/ti/omap/PB-MIKROBUS-0.dtso +--- a/arch/arm/boot/dts/ti/omap/PB-MIKROBUS-0.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/PB-MIKROBUS-0.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,107 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright 2020 Vaishnav M A, BeagleBoard.org Foundation. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ PB-MIKROBUS-0.kernel = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P2_01_pinmux { status = "disabled"; }; ++ P2_03_pinmux { status = "disabled"; }; ++ P2_05_pinmux { status = "disabled"; }; ++ P2_07_pinmux { status = "disabled"; }; ++ P2_09_pinmux { status = "disabled"; }; ++ P2_11_pinmux { status = "disabled"; }; ++ P1_12_pinmux { status = "disabled"; }; ++ P1_10_pinmux { status = "disabled"; }; ++ P1_08_pinmux { status = "disabled"; }; ++ P1_06_pinmux { status = "disabled"; }; ++ P1_04_pinmux { status = "disabled"; }; ++ P1_02_pinmux { status = "disabled"; }; ++}; ++ ++&{/} { ++ aliases { ++ mikrobus0 = "/mikrobus-0"; ++ }; ++ ++ mikrobus-0 { ++ compatible = "linux,mikrobus"; ++ status = "okay"; ++ pinctrl-names = "default", "pwm_default", "pwm_gpio", ++ "uart_default", "uart_gpio", "i2c_default", ++ "i2c_gpio", "spi_default", "spi_gpio"; ++ pinctrl-0 = < ++ &P2_03_gpio_input_pin ++ &P1_04_gpio_pin ++ &P1_02_gpio_pin ++ >; ++ pinctrl-1 = <&P2_01_pwm_pin>; ++ pinctrl-2 = <&P2_01_gpio_pin>; ++ pinctrl-3 = < ++ &P2_05_uart_pin ++ &P2_07_uart_pin ++ >; ++ pinctrl-4 = < ++ &P2_05_gpio_pin ++ &P2_07_gpio_pin ++ >; ++ pinctrl-5 = < ++ &P2_09_i2c_pin ++ &P2_11_i2c_pin ++ >; ++ pinctrl-6 = < ++ &P2_09_gpio_pin ++ &P2_11_gpio_pin ++ >; ++ pinctrl-7 = < ++ &P1_12_spi_pin ++ &P1_10_spi_pin ++ &P1_08_spi_sclk_pin ++ &P1_06_spi_cs_pin ++ >; ++ pinctrl-8 = < ++ &P1_12_gpio_pin ++ &P1_10_gpio_pin ++ &P1_08_gpio_pin ++ &P1_06_gpio_pin ++ >; ++ i2c-adapter = <&i2c1>; ++ spi-master = <0>; ++ spi-cs = <0 1>; ++ uart = <&uart4>; ++ pwms = <&ehrpwm1 0 500000 0>; ++ mikrobus-gpios = <&gpio1 18 0> , <&gpio0 23 0>, ++ <&gpio0 30 0> , <&gpio0 31 0>, ++ <&gpio0 15 0> , <&gpio0 14 0>, ++ <&gpio0 4 0> , <&gpio0 3 0>, ++ <&gpio0 2 0> , <&gpio0 5 0>, ++ <&gpio2 25 0> , <&gpio2 3 0>; ++ }; ++}; ++ ++&spi0 { ++ status = "okay"; ++ channel@0{ status = "disabled"; }; ++}; ++ ++&uart4 { ++ status = "okay"; ++ force-empty-serdev-controller; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/PB-MIKROBUS-1.dtso b/arch/arm/boot/dts/ti/omap/PB-MIKROBUS-1.dtso +--- a/arch/arm/boot/dts/ti/omap/PB-MIKROBUS-1.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/PB-MIKROBUS-1.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,108 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright 2020 Vaishnav M A, BeagleBoard.org Foundation. ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++/* ++ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/ ++ */ ++&{/chosen} { ++ overlays { ++ PB-MIKROBUS-1 = __TIMESTAMP__; ++ }; ++}; ++ ++/* ++ * Free up the pins used by the cape from the pinmux helpers. ++ */ ++&ocp { ++ P1_36_pinmux { status = "disabled"; }; ++ P1_34_pinmux { status = "disabled"; }; ++ P1_32_pinmux { status = "disabled"; }; ++ P1_30_pinmux { status = "disabled"; }; ++ P1_28_pinmux { status = "disabled"; }; ++ P1_26_pinmux { status = "disabled"; }; ++ P2_25_pinmux { status = "disabled"; }; ++ P2_27_pinmux { status = "disabled"; }; ++ P2_29_pinmux { status = "disabled"; }; ++ P2_31_pinmux { status = "disabled"; }; ++ P2_33_pinmux { status = "disabled"; }; ++ P2_35_pinmux { status = "disabled"; }; ++}; ++ ++&{/} { ++ aliases { ++ mikrobus1 = "/mikrobus-1"; ++ }; ++ ++ mikrobus-1 { ++ compatible = "linux,mikrobus"; ++ status = "okay"; ++ pinctrl-names = "default", "pwm_default", "pwm_gpio", ++ "uart_default", "uart_gpio", "i2c_default", ++ "i2c_gpio", "spi_default", "spi_gpio"; ++ pinctrl-0 = < ++ &P1_34_gpio_input_pin ++ &P2_33_gpio_pin ++ &P2_35_gpio_pin ++ >; ++ pinctrl-1 = <&P1_36_pwm_pin>; ++ pinctrl-2 = <&P1_36_gpio_pin>; ++ pinctrl-3 = < ++ &P1_32_uart_pin ++ &P1_30_uart_pin ++ >; ++ pinctrl-4 = < ++ &P1_32_gpio_pin ++ &P1_30_gpio_pin ++ >; ++ pinctrl-5 = < ++ &P1_26_i2c_pin ++ &P1_28_i2c_pin ++ >; ++ pinctrl-6 = < ++ &P1_26_gpio_pin ++ &P1_28_gpio_pin ++ >; ++ pinctrl-7 = < ++ &P2_25_spi_pin ++ &P2_27_spi_pin ++ &P2_29_spi_sclk_pin ++ &P2_31_spi_cs_pin ++ >; ++ pinctrl-8 = < ++ &P2_25_gpio_pin ++ &P2_27_gpio_pin ++ &P2_29_gpio_pin ++ &P2_31_gpio_pin ++ >; ++ i2c-adapter = <&i2c2>; ++ spi-master = <1>; ++ spi-cs = <1 2>; ++ uart = <&uart0>; ++ pwms = <&ehrpwm0 0 500000 0>; ++ mikrobus-gpios = <&gpio3 14 0> , <&gpio0 26 0>, ++ <&gpio1 10 0> , <&gpio1 11 0>, ++ <&gpio0 13 0> , <&gpio0 12 0>, ++ <&gpio1 9 0> , <&gpio1 8 0>, ++ <&gpio0 7 0> , <&gpio0 19 0>, ++ <&gpio1 13 0> , <&gpio2 22 0>; ++ }; ++}; ++ ++&spi1 { ++ status = "okay"; ++ channel@0{ status = "disabled"; }; ++ channel@1{ status = "disabled"; }; ++}; ++ ++&uart0 { ++ status = "okay"; ++ force-empty-serdev-controller; ++}; +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/twl4030.dtsi b/arch/arm/boot/dts/ti/omap/twl4030.dtsi +--- a/arch/arm/boot/dts/ti/omap/twl4030.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/twl4030.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* +- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/ + */ + + /* +diff -Naur --no-dereference a/arch/arm/boot/dts/ti/omap/twl6030.dtsi b/arch/arm/boot/dts/ti/omap/twl6030.dtsi +--- a/arch/arm/boot/dts/ti/omap/twl6030.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/boot/dts/ti/omap/twl6030.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,11 +1,11 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* +- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ ++ * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/ + */ + + /* + * Integrated Power Management Chip +- * http://www.ti.com/lit/ds/symlink/twl6030.pdf ++ * https://www.ti.com/lit/ds/symlink/twl6030.pdf + */ + &twl { + compatible = "ti,twl6030"; +diff -Naur --no-dereference a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig +--- a/arch/arm/configs/keystone_defconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/configs/keystone_defconfig 2024-03-28 11:26:09.893017428 -0400 +@@ -98,7 +98,6 @@ + CONFIG_IP_NF_FILTER=y + CONFIG_IP_NF_TARGET_REJECT=y + CONFIG_IP_NF_MANGLE=y +-CONFIG_IP_NF_TARGET_CLUSTERIP=y + CONFIG_IP_NF_TARGET_ECN=y + CONFIG_IP_NF_TARGET_TTL=y + CONFIG_IP_NF_RAW=y +diff -Naur --no-dereference a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig +--- a/arch/arm/configs/multi_v7_defconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/configs/multi_v7_defconfig 2024-03-28 11:26:09.893017428 -0400 +@@ -857,7 +857,6 @@ + CONFIG_USB_MUSB_SUNXI=m + CONFIG_USB_MUSB_TUSB6010=m + CONFIG_USB_MUSB_OMAP2PLUS=m +-CONFIG_USB_MUSB_AM35X=m + CONFIG_USB_MUSB_DSPS=m + CONFIG_USB_MUSB_UX500=m + CONFIG_USB_UX500_DMA=y +@@ -1189,6 +1188,7 @@ + CONFIG_PWM_VT8500=y + CONFIG_KEYSTONE_IRQ=y + CONFIG_RESET_MCHP_SPARX5=y ++CONFIG_RESET_SCMI=y + CONFIG_PHY_SUN4I_USB=y + CONFIG_PHY_SUN9I_USB=y + CONFIG_PHY_BRCM_USB=m +diff -Naur --no-dereference a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig +--- a/arch/arm/configs/omap2plus_defconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm/configs/omap2plus_defconfig 2024-03-28 11:26:09.893017428 -0400 +@@ -78,7 +78,6 @@ + CONFIG_IP_PNP_RARP=y + CONFIG_NETFILTER=y + CONFIG_NF_CONNTRACK=m +-CONFIG_NF_LOG_NETDEV=m + CONFIG_NF_CONNTRACK_ZONES=y + CONFIG_NF_CONNTRACK_EVENTS=y + CONFIG_NF_CONNTRACK_TIMEOUT=y +@@ -92,7 +91,6 @@ + CONFIG_NF_TABLES_NETDEV=y + CONFIG_NFT_NUMGEN=m + CONFIG_NFT_CT=m +-CONFIG_NFT_COUNTER=m + CONFIG_NFT_CONNLIMIT=m + CONFIG_NFT_LOG=m + CONFIG_NFT_LIMIT=m +@@ -100,7 +98,6 @@ + CONFIG_NFT_REDIR=m + CONFIG_NFT_NAT=m + CONFIG_NFT_TUNNEL=m +-CONFIG_NFT_OBJREF=m + CONFIG_NFT_QUEUE=m + CONFIG_NFT_QUOTA=m + CONFIG_NFT_REJECT=m +@@ -179,7 +176,6 @@ + CONFIG_NETFILTER_XT_MATCH_U32=m + CONFIG_NFT_DUP_IPV4=m + CONFIG_NFT_FIB_IPV4=m +-CONFIG_NF_FLOW_TABLE_IPV4=m + CONFIG_IP_NF_IPTABLES=m + CONFIG_IP_NF_MATCH_AH=m + CONFIG_IP_NF_MATCH_ECN=m +@@ -193,14 +189,12 @@ + CONFIG_IP_NF_TARGET_NETMAP=m + CONFIG_IP_NF_TARGET_REDIRECT=m + CONFIG_IP_NF_MANGLE=m +-CONFIG_IP_NF_TARGET_CLUSTERIP=m + CONFIG_IP_NF_TARGET_ECN=m + CONFIG_IP_NF_TARGET_TTL=m + CONFIG_IP_NF_RAW=m + CONFIG_IP_NF_SECURITY=m + CONFIG_NFT_DUP_IPV6=m + CONFIG_NFT_FIB_IPV6=m +-CONFIG_NF_FLOW_TABLE_IPV6=m + CONFIG_IP6_NF_IPTABLES=m + CONFIG_IP6_NF_MATCH_AH=m + CONFIG_IP6_NF_MATCH_EUI64=m +@@ -225,7 +219,6 @@ + CONFIG_NF_TABLES_BRIDGE=m + CONFIG_NFT_BRIDGE_META=m + CONFIG_NFT_BRIDGE_REJECT=m +-CONFIG_NF_LOG_BRIDGE=m + CONFIG_BRIDGE=m + CONFIG_BRIDGE_VLAN_FILTERING=y + CONFIG_VLAN_8021Q=m +@@ -560,7 +553,6 @@ + CONFIG_USB_MUSB_HDRC=m + CONFIG_USB_MUSB_TUSB6010=m + CONFIG_USB_MUSB_OMAP2PLUS=m +-CONFIG_USB_MUSB_AM35X=m + CONFIG_USB_MUSB_DSPS=m + CONFIG_USB_INVENTRA_DMA=y + CONFIG_USB_TI_CPPI41_DMA=y +diff -Naur --no-dereference a/arch/arm/configs/rcn-ee_defconfig b/arch/arm/configs/rcn-ee_defconfig +--- a/arch/arm/configs/rcn-ee_defconfig 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm/configs/rcn-ee_defconfig 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,2864 @@ ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_KERNEL_LZ4=y ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ_IDLE=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_BPF_JIT=y ++CONFIG_BPF_LSM=y ++CONFIG_PREEMPT=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_PSI=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_IKHEADERS=m ++CONFIG_LOG_BUF_SHIFT=16 ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CFS_BANDWIDTH=y ++CONFIG_CGROUP_PIDS=y ++CONFIG_CGROUP_RDMA=y ++CONFIG_CGROUP_FREEZER=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_BPF=y ++CONFIG_CGROUP_MISC=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_CHECKPOINT_RESTORE=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_EXPERT=y ++# CONFIG_SYSFS_SYSCALL is not set ++CONFIG_PROFILING=y ++CONFIG_KEXEC=y ++CONFIG_CRASH_DUMP=y ++CONFIG_SOC_OMAP5=y ++CONFIG_SOC_AM33XX=y ++CONFIG_SOC_DRA7XX=y ++CONFIG_SOC_HAS_OMAP2_SDRC=y ++CONFIG_OMAP5_ERRATA_801819=y ++CONFIG_ARM_THUMBEE=y ++CONFIG_PL310_ERRATA_588369=y ++CONFIG_PL310_ERRATA_727915=y ++CONFIG_PL310_ERRATA_753970=y ++CONFIG_ARM_ERRATA_430973=y ++CONFIG_ARM_ERRATA_773022=y ++CONFIG_ARM_ERRATA_814220=y ++CONFIG_SMP=y ++# CONFIG_ARM_CPU_TOPOLOGY is not set ++CONFIG_MCPM=y ++CONFIG_NR_CPUS=2 ++CONFIG_ARM_PSCI=y ++CONFIG_HZ_250=y ++CONFIG_ARCH_FORCE_MAX_ORDER=12 ++CONFIG_PARAVIRT=y ++# CONFIG_ATAGS is not set ++CONFIG_EFI=y ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=m ++CONFIG_CPU_FREQ_GOV_USERSPACE=m ++CONFIG_CPU_FREQ_GOV_ONDEMAND=m ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m ++CONFIG_CPUFREQ_DT=m ++CONFIG_CPUFREQ_DT_PLATDEV=y ++# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set ++CONFIG_CPU_IDLE=y ++CONFIG_CPU_IDLE_GOV_LADDER=y ++CONFIG_ARM_CPUIDLE=y ++CONFIG_ARM_PSCI_CPUIDLE=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_HIBERNATION=y ++CONFIG_PM_AUTOSLEEP=y ++CONFIG_PM_WAKELOCKS=y ++CONFIG_PM_DEBUG=y ++CONFIG_PM_ADVANCED_DEBUG=y ++CONFIG_APM_EMULATION=y ++CONFIG_ENERGY_MODEL=y ++CONFIG_KPROBES=y ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_FORCE_LOAD=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_COMPRESS_XZ=y ++CONFIG_BLK_DEV_ZONED=y ++CONFIG_BLK_DEV_THROTTLING=y ++CONFIG_BLK_WBT=y ++CONFIG_BLK_CGROUP_IOCOST=y ++CONFIG_BLK_SED_OPAL=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_KARMA_PARTITION=y ++CONFIG_MQ_IOSCHED_KYBER=m ++CONFIG_IOSCHED_BFQ=m ++CONFIG_BINFMT_MISC=m ++CONFIG_ZSWAP=y ++CONFIG_Z3FOLD=m ++CONFIG_SLAB_FREELIST_RANDOM=y ++CONFIG_SLAB_FREELIST_HARDENED=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_KSM=y ++CONFIG_USERFAULTFD=y ++CONFIG_LRU_GEN=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_PACKET_DIAG=m ++CONFIG_UNIX_DIAG=m ++CONFIG_TLS=m ++CONFIG_TLS_DEVICE=y ++CONFIG_XFRM_USER=m ++CONFIG_XFRM_INTERFACE=m ++CONFIG_XFRM_SUB_POLICY=y ++CONFIG_XFRM_STATISTICS=y ++CONFIG_NET_KEY=m ++CONFIG_NET_KEY_MIGRATE=y ++CONFIG_XDP_SOCKETS=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_FIB_TRIE_STATS=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_BROADCAST=y ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_NET_IPVTI=m ++CONFIG_NET_FOU_IP_TUNNELS=y ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_ESP_OFFLOAD=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_DIAG=m ++CONFIG_INET_UDP_DIAG=m ++CONFIG_INET_RAW_DIAG=m ++CONFIG_INET_DIAG_DESTROY=y ++CONFIG_TCP_CONG_ADVANCED=y ++CONFIG_TCP_CONG_HSTCP=m ++CONFIG_TCP_CONG_HYBLA=m ++CONFIG_TCP_CONG_NV=m ++CONFIG_TCP_CONG_SCALABLE=m ++CONFIG_TCP_CONG_LP=m ++CONFIG_TCP_CONG_VENO=m ++CONFIG_TCP_CONG_YEAH=m ++CONFIG_TCP_CONG_ILLINOIS=m ++CONFIG_TCP_CONG_DCTCP=m ++CONFIG_TCP_CONG_CDG=m ++CONFIG_TCP_CONG_BBR=m ++CONFIG_TCP_MD5SIG=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_ROUTE_INFO=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_ESP_OFFLOAD=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MIP6=y ++CONFIG_IPV6_ILA=m ++CONFIG_IPV6_VTI=m ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_SIT_6RD=y ++CONFIG_IPV6_GRE=m ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IPV6_PIMSM_V2=y ++CONFIG_IPV6_SEG6_LWTUNNEL=y ++CONFIG_IPV6_SEG6_HMAC=y ++CONFIG_NETLABEL=y ++CONFIG_MPTCP=y ++CONFIG_NETWORK_PHY_TIMESTAMPING=y ++CONFIG_NETFILTER=y ++CONFIG_BRIDGE_NETFILTER=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_SECMARK=y ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_PROCFS=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMEOUT=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NF_CT_NETLINK_TIMEOUT=m ++CONFIG_NF_CT_NETLINK_HELPER=m ++CONFIG_NETFILTER_NETLINK_GLUE_CT=y ++CONFIG_NF_TABLES=m ++CONFIG_NF_TABLES_INET=y ++CONFIG_NF_TABLES_NETDEV=y ++CONFIG_NFT_NUMGEN=m ++CONFIG_NFT_CT=m ++CONFIG_NFT_FLOW_OFFLOAD=m ++CONFIG_NFT_CONNLIMIT=m ++CONFIG_NFT_LOG=m ++CONFIG_NFT_LIMIT=m ++CONFIG_NFT_MASQ=m ++CONFIG_NFT_REDIR=m ++CONFIG_NFT_NAT=m ++CONFIG_NFT_TUNNEL=m ++CONFIG_NFT_QUEUE=m ++CONFIG_NFT_QUOTA=m ++CONFIG_NFT_REJECT=m ++CONFIG_NFT_COMPAT=m ++CONFIG_NFT_HASH=m ++CONFIG_NFT_FIB_INET=m ++CONFIG_NFT_XFRM=m ++CONFIG_NFT_SOCKET=m ++CONFIG_NFT_OSF=m ++CONFIG_NFT_TPROXY=m ++CONFIG_NFT_SYNPROXY=m ++CONFIG_NFT_DUP_NETDEV=m ++CONFIG_NFT_FWD_NETDEV=m ++CONFIG_NFT_FIB_NETDEV=m ++CONFIG_NF_FLOW_TABLE_INET=m ++CONFIG_NF_FLOW_TABLE=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_AUDIT=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m ++CONFIG_NETFILTER_XT_TARGET_CT=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_HMARK=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_SECMARK=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_BPF=m ++CONFIG_NETFILTER_XT_MATCH_CGROUP=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPCOMP=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_NFACCT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPMARK=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_IPMAC=m ++CONFIG_IP_SET_HASH_MAC=m ++CONFIG_IP_SET_HASH_NETPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETNET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_IP_VS=m ++CONFIG_IP_VS_IPV6=y ++CONFIG_IP_VS_PROTO_TCP=y ++CONFIG_IP_VS_PROTO_UDP=y ++CONFIG_IP_VS_PROTO_ESP=y ++CONFIG_IP_VS_PROTO_AH=y ++CONFIG_IP_VS_PROTO_SCTP=y ++CONFIG_IP_VS_RR=m ++CONFIG_IP_VS_WRR=m ++CONFIG_IP_VS_LC=m ++CONFIG_IP_VS_WLC=m ++CONFIG_IP_VS_FO=m ++CONFIG_IP_VS_OVF=m ++CONFIG_IP_VS_LBLC=m ++CONFIG_IP_VS_LBLCR=m ++CONFIG_IP_VS_DH=m ++CONFIG_IP_VS_SH=m ++CONFIG_IP_VS_MH=m ++CONFIG_IP_VS_SED=m ++CONFIG_IP_VS_NQ=m ++CONFIG_IP_VS_FTP=m ++CONFIG_IP_VS_PE_SIP=m ++CONFIG_NFT_DUP_IPV4=m ++CONFIG_NFT_FIB_IPV4=m ++CONFIG_NF_TABLES_ARP=y ++CONFIG_NF_LOG_ARP=m ++CONFIG_NF_LOG_IPV4=m ++CONFIG_IP_NF_IPTABLES=y ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_RPFILTER=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_TARGET_SYNPROXY=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_SECURITY=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NFT_DUP_IPV6=m ++CONFIG_NFT_FIB_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RPFILTER=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_MATCH_SRH=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_TARGET_SYNPROXY=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_IP6_NF_SECURITY=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_NPT=m ++CONFIG_NF_TABLES_BRIDGE=m ++CONFIG_NFT_BRIDGE_META=m ++CONFIG_NFT_BRIDGE_REJECT=m ++CONFIG_NF_CONNTRACK_BRIDGE=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_IP_DCCP=m ++CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y ++CONFIG_SCTP_COOKIE_HMAC_MD5=y ++CONFIG_RDS=m ++CONFIG_RDS_TCP=m ++CONFIG_TIPC=m ++CONFIG_ATM=m ++CONFIG_ATM_CLIP=m ++CONFIG_ATM_LANE=m ++CONFIG_ATM_MPOA=m ++CONFIG_ATM_BR2684=m ++CONFIG_L2TP=m ++CONFIG_L2TP_DEBUGFS=m ++CONFIG_L2TP_V3=y ++CONFIG_L2TP_IP=m ++CONFIG_L2TP_ETH=m ++CONFIG_BRIDGE=m ++CONFIG_BRIDGE_VLAN_FILTERING=y ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_VLAN_8021Q_MVRP=y ++CONFIG_LLC2=m ++CONFIG_ATALK=m ++CONFIG_PHONET=m ++CONFIG_6LOWPAN=m ++CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m ++CONFIG_6LOWPAN_GHC_UDP=m ++CONFIG_6LOWPAN_GHC_ICMPV6=m ++CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m ++CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m ++CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m ++CONFIG_IEEE802154=m ++CONFIG_IEEE802154_6LOWPAN=m ++CONFIG_MAC802154=m ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_CBS=m ++CONFIG_NET_SCH_ETF=m ++CONFIG_NET_SCH_TAPRIO=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_SKBPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_SCH_CODEL=m ++CONFIG_NET_SCH_FQ_CODEL=y ++CONFIG_NET_SCH_CAKE=m ++CONFIG_NET_SCH_FQ=m ++CONFIG_NET_SCH_HHF=m ++CONFIG_NET_SCH_PIE=m ++CONFIG_NET_SCH_FQ_PIE=m ++CONFIG_NET_SCH_INGRESS=m ++CONFIG_NET_SCH_PLUG=m ++CONFIG_NET_SCH_ETS=m ++CONFIG_NET_SCH_DEFAULT=y ++CONFIG_DEFAULT_FQ_CODEL=y ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_PERF=y ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=y ++CONFIG_NET_CLS_BPF=m ++CONFIG_NET_CLS_FLOWER=m ++CONFIG_NET_CLS_MATCHALL=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_EMATCH_CANID=m ++CONFIG_NET_EMATCH_IPSET=m ++CONFIG_NET_EMATCH_IPT=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_SAMPLE=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++CONFIG_NET_ACT_MPLS=m ++CONFIG_NET_ACT_VLAN=m ++CONFIG_NET_ACT_BPF=m ++CONFIG_NET_ACT_CONNMARK=m ++CONFIG_NET_ACT_CTINFO=m ++CONFIG_NET_ACT_SKBMOD=m ++CONFIG_NET_ACT_IFE=m ++CONFIG_NET_ACT_TUNNEL_KEY=m ++CONFIG_NET_ACT_CT=m ++CONFIG_NET_ACT_GATE=m ++CONFIG_NET_IFE_SKBMARK=m ++CONFIG_NET_IFE_SKBPRIO=m ++CONFIG_NET_IFE_SKBTCINDEX=m ++CONFIG_DCB=y ++CONFIG_BATMAN_ADV=m ++CONFIG_BATMAN_ADV_NC=y ++CONFIG_OPENVSWITCH=m ++CONFIG_VSOCKETS=m ++CONFIG_VIRTIO_VSOCKETS=m ++CONFIG_NETLINK_DIAG=m ++CONFIG_NET_MPLS_GSO=y ++CONFIG_MPLS_ROUTING=m ++CONFIG_MPLS_IPTUNNEL=m ++CONFIG_HSR=m ++CONFIG_NET_SWITCHDEV=y ++CONFIG_QRTR=m ++CONFIG_QRTR_SMD=m ++CONFIG_QRTR_TUN=m ++CONFIG_NET_NCSI=y ++CONFIG_CGROUP_NET_PRIO=y ++CONFIG_BPF_STREAM_PARSER=y ++CONFIG_NET_PKTGEN=m ++CONFIG_NET_DROP_MONITOR=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m ++CONFIG_CAN=m ++CONFIG_CAN_J1939=m ++CONFIG_CAN_ISOTP=m ++CONFIG_BT=m ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=m ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_HS=y ++CONFIG_BT_6LOWPAN=m ++CONFIG_BT_LEDS=y ++CONFIG_BT_MSFTEXT=y ++CONFIG_BT_HCIBTUSB=m ++CONFIG_BT_HCIBTUSB_MTK=y ++CONFIG_BT_HCIBTSDIO=m ++CONFIG_BT_HCIUART=m ++CONFIG_BT_HCIUART_NOKIA=m ++CONFIG_BT_HCIUART_ATH3K=y ++CONFIG_BT_HCIUART_LL=y ++CONFIG_BT_HCIUART_INTEL=y ++CONFIG_BT_HCIUART_BCM=y ++CONFIG_BT_HCIUART_RTL=y ++CONFIG_BT_HCIUART_QCA=y ++CONFIG_BT_HCIUART_AG6XX=y ++CONFIG_BT_HCIUART_MRVL=y ++CONFIG_BT_MRVL=m ++CONFIG_BT_MRVL_SDIO=m ++CONFIG_BT_ATH3K=m ++CONFIG_BT_MTKUART=m ++CONFIG_AF_RXRPC_IPV6=y ++CONFIG_RXKAD=y ++CONFIG_AF_KCM=m ++CONFIG_CFG80211=m ++# CONFIG_CFG80211_DEFAULT_PS is not set ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_RFKILL=y ++CONFIG_RFKILL_INPUT=y ++CONFIG_NET_9P=m ++CONFIG_NET_9P_VIRTIO=m ++CONFIG_NFC=m ++CONFIG_NFC_DIGITAL=m ++CONFIG_NFC_NCI=m ++CONFIG_NFC_NCI_SPI=m ++CONFIG_NFC_NCI_UART=m ++CONFIG_NFC_TRF7970A=m ++CONFIG_NFC_SIM=m ++CONFIG_NFC_PORT100=m ++CONFIG_NFC_PN533_USB=m ++CONFIG_NFC_PN533_I2C=m ++CONFIG_NFC_ST_NCI_I2C=m ++CONFIG_NFC_ST_NCI_SPI=m ++CONFIG_NFC_NXP_NCI=m ++CONFIG_NFC_NXP_NCI_I2C=m ++CONFIG_NFC_ST95HF=m ++CONFIG_PAGE_POOL_STATS=y ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_EXTRA_FIRMWARE="regulatory.db regulatory.db.p7s am335x-pm-firmware.elf am335x-bone-scale-data.bin am335x-evm-scale-data.bin am43x-evm-scale-data.bin" ++CONFIG_EXTRA_FIRMWARE_DIR="firmware" ++CONFIG_OMAP_OCP2SCP=y ++CONFIG_CONNECTOR=y ++CONFIG_DMI_SYSFS=y ++CONFIG_TRUSTED_FOUNDATIONS=y ++CONFIG_EFI_BOOTLOADER_CONTROL=m ++CONFIG_EFI_CAPSULE_LOADER=m ++CONFIG_RESET_ATTACK_MITIGATION=y ++CONFIG_GNSS=m ++CONFIG_GNSS_MTK_SERIAL=m ++CONFIG_GNSS_SIRF_SERIAL=m ++CONFIG_GNSS_UBX_SERIAL=m ++CONFIG_MTD=y ++CONFIG_MTD_AR7_PARTS=m ++CONFIG_MTD_OF_PARTS=m ++CONFIG_MTD_BLOCK=m ++CONFIG_MTD_BLOCK_RO=m ++CONFIG_RFD_FTL=m ++CONFIG_SSFDC=m ++CONFIG_MTD_OOPS=m ++CONFIG_MTD_SWAP=m ++CONFIG_MTD_PHYSMAP=m ++CONFIG_MTD_PLATRAM=m ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_SST25L=m ++CONFIG_MTD_ONENAND=y ++CONFIG_MTD_ONENAND_VERIFY_WRITE=y ++CONFIG_MTD_ONENAND_2X_PROGRAM=y ++CONFIG_MTD_RAW_NAND=y ++CONFIG_MTD_NAND_OMAP2=m ++CONFIG_MTD_NAND_NANDSIM=m ++CONFIG_MTD_NAND_ECC_SW_BCH=y ++CONFIG_MTD_LPDDR=m ++CONFIG_MTD_SPI_NOR=m ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_BLOCK=y ++CONFIG_OF_OVERLAY=y ++CONFIG_BLK_DEV_NULL_BLK=m ++CONFIG_ZRAM=m ++CONFIG_ZRAM_WRITEBACK=y ++CONFIG_ZRAM_MEMORY_TRACKING=y ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_DRBD=m ++CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=m ++CONFIG_BLK_DEV_RAM_SIZE=16384 ++CONFIG_ATA_OVER_ETH=m ++CONFIG_VIRTIO_BLK=m ++CONFIG_BLK_DEV_RBD=m ++CONFIG_AD525X_DPOT=m ++CONFIG_AD525X_DPOT_I2C=m ++CONFIG_AD525X_DPOT_SPI=m ++CONFIG_ICS932S401=m ++CONFIG_APDS9802ALS=m ++CONFIG_ISL29003=m ++CONFIG_ISL29020=m ++CONFIG_SENSORS_TSL2550=m ++CONFIG_SENSORS_BH1770=m ++CONFIG_SENSORS_APDS990X=m ++CONFIG_HMC6352=m ++CONFIG_DS1682=m ++CONFIG_SRAM=y ++CONFIG_EEPROM_AT24=y ++CONFIG_EEPROM_AT25=y ++CONFIG_EEPROM_LEGACY=m ++CONFIG_EEPROM_MAX6875=m ++CONFIG_EEPROM_93XX46=m ++CONFIG_EEPROM_EE1004=m ++CONFIG_TI_ST=m ++CONFIG_RAID_ATTRS=m ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_BLK_DEV_SR=m ++CONFIG_CHR_DEV_SG=m ++CONFIG_CHR_DEV_SCH=m ++CONFIG_SCSI_CONSTANTS=y ++CONFIG_SCSI_LOGGING=y ++CONFIG_SCSI_SCAN_ASYNC=y ++CONFIG_SCSI_SPI_ATTRS=m ++CONFIG_SCSI_FC_ATTRS=m ++CONFIG_SCSI_ISCSI_ATTRS=m ++CONFIG_SCSI_SAS_LIBSAS=m ++CONFIG_SCSI_SAS_ATA=y ++CONFIG_SCSI_SRP_ATTRS=m ++CONFIG_ATA=y ++CONFIG_SATA_AHCI_PLATFORM=y ++CONFIG_MD=y ++CONFIG_BLK_DEV_MD=m ++CONFIG_MD_LINEAR=m ++CONFIG_MD_RAID0=m ++CONFIG_MD_RAID1=m ++CONFIG_MD_RAID10=m ++CONFIG_MD_MULTIPATH=m ++CONFIG_MD_FAULTY=m ++CONFIG_MD_CLUSTER=m ++CONFIG_BCACHE=m ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_UNSTRIPED=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DM_CACHE=m ++CONFIG_DM_WRITECACHE=m ++CONFIG_DM_ERA=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_MULTIPATH=m ++CONFIG_DM_MULTIPATH_QL=m ++CONFIG_DM_MULTIPATH_ST=m ++CONFIG_DM_DELAY=m ++CONFIG_DM_UEVENT=y ++CONFIG_DM_FLAKEY=m ++CONFIG_DM_VERITY=m ++CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y ++CONFIG_DM_SWITCH=m ++CONFIG_DM_LOG_WRITES=m ++CONFIG_DM_INTEGRITY=m ++CONFIG_DM_ZONED=m ++CONFIG_TARGET_CORE=m ++CONFIG_TCM_IBLOCK=m ++CONFIG_TCM_FILEIO=m ++CONFIG_TCM_PSCSI=m ++CONFIG_TCM_USER2=m ++CONFIG_LOOPBACK_TARGET=m ++CONFIG_ISCSI_TARGET=m ++CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_DUMMY=m ++CONFIG_WIREGUARD=m ++CONFIG_EQUALIZER=m ++CONFIG_IFB=m ++CONFIG_NET_TEAM=m ++CONFIG_NET_TEAM_MODE_BROADCAST=m ++CONFIG_NET_TEAM_MODE_ROUNDROBIN=m ++CONFIG_NET_TEAM_MODE_RANDOM=m ++CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m ++CONFIG_NET_TEAM_MODE_LOADBALANCE=m ++CONFIG_MACVLAN=m ++CONFIG_MACVTAP=m ++CONFIG_IPVLAN=m ++CONFIG_IPVTAP=m ++CONFIG_VXLAN=m ++CONFIG_GENEVE=m ++CONFIG_GTP=m ++CONFIG_MACSEC=m ++CONFIG_NETCONSOLE=m ++CONFIG_NETCONSOLE_DYNAMIC=y ++CONFIG_TUN=m ++CONFIG_VETH=m ++CONFIG_VIRTIO_NET=m ++CONFIG_NLMON=m ++CONFIG_NET_VRF=m ++CONFIG_ATM_DUMMY=m ++# CONFIG_NET_VENDOR_ALACRITECH is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AQUANTIA is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_CADENCE is not set ++# CONFIG_NET_VENDOR_CAVIUM is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++# CONFIG_NET_VENDOR_CORTINA is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++# CONFIG_NET_VENDOR_GOOGLE is not set ++# CONFIG_NET_VENDOR_HISILICON is not set ++# CONFIG_NET_VENDOR_HUAWEI is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_MELLANOX is not set ++CONFIG_KS8851=m ++CONFIG_ENC28J60=y ++CONFIG_ENCX24J600=y ++# CONFIG_NET_VENDOR_NI is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++# CONFIG_NET_VENDOR_PENSANDO is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++# CONFIG_NET_VENDOR_ROCKER is not set ++# CONFIG_NET_VENDOR_SAMSUNG is not set ++# CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_SOLARFLARE is not set ++CONFIG_SMC91X=m ++CONFIG_SMSC911X=m ++# CONFIG_NET_VENDOR_SOCIONEXT is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_TI_CPSW_PHY_SEL=y ++CONFIG_TI_CPSW=y ++CONFIG_TI_CPSW_SWITCHDEV=y ++CONFIG_TI_CPTS=y ++# CONFIG_NET_VENDOR_VIA is not set ++CONFIG_WIZNET_W5100=y ++CONFIG_WIZNET_W5100_SPI=y ++# CONFIG_NET_VENDOR_XILINX is not set ++CONFIG_LED_TRIGGER_PHY=y ++CONFIG_MICREL_PHY=y ++CONFIG_MICROCHIP_PHY=y ++CONFIG_MICROSEMI_PHY=m ++CONFIG_AT803X_PHY=y ++CONFIG_DP83867_PHY=y ++CONFIG_DP83869_PHY=m ++CONFIG_VITESSE_PHY=y ++CONFIG_CAN_VCAN=m ++CONFIG_CAN_VXCAN=m ++CONFIG_CAN_SLCAN=m ++CONFIG_CAN_C_CAN=m ++CONFIG_CAN_C_CAN_PLATFORM=m ++CONFIG_CAN_HI311X=m ++CONFIG_CAN_MCP251X=m ++CONFIG_CAN_MCP251XFD=m ++CONFIG_CAN_8DEV_USB=m ++CONFIG_CAN_EMS_USB=m ++CONFIG_CAN_ESD_USB=m ++CONFIG_CAN_GS_USB=m ++CONFIG_CAN_KVASER_USB=m ++CONFIG_CAN_MCBA_USB=m ++CONFIG_CAN_PEAK_USB=m ++CONFIG_CAN_UCAN=m ++CONFIG_MDIO_BCM_UNIMAC=m ++CONFIG_MDIO_GPIO=y ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOATM=m ++CONFIG_PPPOE=m ++CONFIG_PPTP=m ++CONFIG_PPPOL2TP=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y ++CONFIG_SLIP_MODE_SLIP6=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_RTL8152=m ++CONFIG_USB_LAN78XX=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_AX88179_178A=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_CDC_NCM=m ++CONFIG_USB_NET_HUAWEI_CDC_NCM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SR9700=m ++CONFIG_USB_NET_SR9800=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_ZAURUS=m ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_HSO=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_CDC_PHONET=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m ++CONFIG_USB_NET_CH9200=m ++CONFIG_USB_NET_AQC111=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_CHANNEL_CONTEXT=y ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_ATH6KL=m ++CONFIG_ATH6KL_SDIO=m ++CONFIG_ATH6KL_USB=m ++CONFIG_AR5523=m ++CONFIG_ATH10K=m ++CONFIG_ATH10K_SDIO=m ++CONFIG_ATH10K_USB=m ++CONFIG_ATH11K=m ++CONFIG_ATH11K_AHB=m ++CONFIG_AT76C50X_USB=m ++CONFIG_BRCMFMAC=m ++# CONFIG_WLAN_VENDOR_CISCO is not set ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_LIBERTAS_MESH=y ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_USB=m ++CONFIG_MT7601U=m ++CONFIG_MT76x0U=m ++CONFIG_MT76x2U=m ++CONFIG_MT7663U=m ++CONFIG_MT7663S=m ++CONFIG_MT7921S=m ++CONFIG_MT7921U=m ++CONFIG_WILC1000_SDIO=m ++CONFIG_WILC1000_SPI=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT3573=y ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_RT2800USB_RT55XX=y ++CONFIG_RTL8187=m ++CONFIG_RTL8192CU=m ++# CONFIG_RTLWIFI_DEBUG is not set ++CONFIG_RTL8XXXU=m ++CONFIG_RTW88=m ++CONFIG_RTW89=m ++CONFIG_RSI_91X=m ++# CONFIG_RSI_SDIO is not set ++CONFIG_WL1251=m ++CONFIG_WL1251_SPI=m ++CONFIG_WL1251_SDIO=m ++CONFIG_WL12XX=m ++CONFIG_WL18XX=m ++CONFIG_WLCORE_SPI=m ++CONFIG_WLCORE_SDIO=m ++CONFIG_ZD1211RW=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_IEEE802154_AT86RF230=m ++CONFIG_IEEE802154_MRF24J40=m ++CONFIG_IEEE802154_CC2520=m ++CONFIG_IEEE802154_ATUSB=m ++CONFIG_IEEE802154_ADF7242=m ++CONFIG_IEEE802154_CA8210=m ++CONFIG_IEEE802154_MCR20A=m ++CONFIG_IEEE802154_HWSIM=m ++CONFIG_INPUT_SPARSEKMAP=m ++CONFIG_INPUT_JOYDEV=m ++CONFIG_INPUT_EVDEV=m ++CONFIG_KEYBOARD_ADP5588=m ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_QT2160=m ++CONFIG_KEYBOARD_GPIO=y ++CONFIG_KEYBOARD_TCA8418=m ++CONFIG_KEYBOARD_LM8323=m ++CONFIG_KEYBOARD_MAX7359=m ++CONFIG_KEYBOARD_STOWAWAY=m ++# CONFIG_MOUSE_PS2 is not set ++CONFIG_MOUSE_APPLETOUCH=m ++CONFIG_MOUSE_ELAN_I2C=m ++CONFIG_MOUSE_SYNAPTICS_I2C=m ++CONFIG_MOUSE_SYNAPTICS_USB=m ++CONFIG_INPUT_JOYSTICK=y ++CONFIG_JOYSTICK_IFORCE=m ++CONFIG_JOYSTICK_IFORCE_USB=m ++CONFIG_JOYSTICK_IFORCE_232=m ++CONFIG_JOYSTICK_WARRIOR=m ++CONFIG_JOYSTICK_MAGELLAN=m ++CONFIG_JOYSTICK_SPACEORB=m ++CONFIG_JOYSTICK_SPACEBALL=m ++CONFIG_JOYSTICK_STINGER=m ++CONFIG_JOYSTICK_TWIDJOY=m ++CONFIG_JOYSTICK_ZHENHUA=m ++CONFIG_JOYSTICK_AS5011=m ++CONFIG_JOYSTICK_XPAD=m ++CONFIG_JOYSTICK_XPAD_FF=y ++CONFIG_JOYSTICK_XPAD_LEDS=y ++CONFIG_JOYSTICK_PSXPAD_SPI=y ++CONFIG_JOYSTICK_PSXPAD_SPI_FF=y ++CONFIG_JOYSTICK_PXRC=m ++CONFIG_JOYSTICK_FSIA6B=m ++CONFIG_INPUT_TABLET=y ++CONFIG_TABLET_USB_ACECAD=m ++CONFIG_TABLET_USB_AIPTEK=m ++CONFIG_TABLET_USB_HANWANG=m ++CONFIG_TABLET_USB_KBTAB=m ++CONFIG_TABLET_USB_PEGASUS=m ++CONFIG_TABLET_SERIAL_WACOM4=m ++CONFIG_INPUT_TOUCHSCREEN=y ++CONFIG_TOUCHSCREEN_ADS7846=m ++CONFIG_TOUCHSCREEN_AD7877=m ++CONFIG_TOUCHSCREEN_AD7879=m ++CONFIG_TOUCHSCREEN_AD7879_I2C=m ++CONFIG_TOUCHSCREEN_AR1021_I2C=y ++CONFIG_TOUCHSCREEN_ATMEL_MXT=m ++CONFIG_TOUCHSCREEN_DYNAPRO=m ++CONFIG_TOUCHSCREEN_HAMPSHIRE=m ++CONFIG_TOUCHSCREEN_EETI=m ++CONFIG_TOUCHSCREEN_FUJITSU=m ++CONFIG_TOUCHSCREEN_GOODIX=m ++CONFIG_TOUCHSCREEN_GUNZE=m ++CONFIG_TOUCHSCREEN_ELAN=m ++CONFIG_TOUCHSCREEN_ELO=m ++CONFIG_TOUCHSCREEN_WACOM_W8001=m ++CONFIG_TOUCHSCREEN_MCS5000=m ++CONFIG_TOUCHSCREEN_MTOUCH=m ++CONFIG_TOUCHSCREEN_INEXIO=m ++CONFIG_TOUCHSCREEN_PENMOUNT=m ++CONFIG_TOUCHSCREEN_EDT_FT5X06=y ++CONFIG_TOUCHSCREEN_TOUCHRIGHT=m ++CONFIG_TOUCHSCREEN_TOUCHWIN=m ++CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y ++CONFIG_TOUCHSCREEN_USB_COMPOSITE=m ++CONFIG_TOUCHSCREEN_TOUCHIT213=m ++CONFIG_TOUCHSCREEN_TSC2005=m ++CONFIG_TOUCHSCREEN_TSC2007=m ++CONFIG_TOUCHSCREEN_SILEAD=y ++CONFIG_TOUCHSCREEN_STMPE=y ++CONFIG_TOUCHSCREEN_TPS6507X=m ++CONFIG_INPUT_MISC=y ++CONFIG_INPUT_AD714X=m ++CONFIG_INPUT_MMA8450=m ++CONFIG_INPUT_GPIO_DECODER=m ++CONFIG_INPUT_ATI_REMOTE2=m ++CONFIG_INPUT_KEYSPAN_REMOTE=m ++CONFIG_INPUT_POWERMATE=m ++CONFIG_INPUT_YEALINK=m ++CONFIG_INPUT_CM109=m ++CONFIG_INPUT_TPS65218_PWRBUTTON=y ++CONFIG_INPUT_TPS65219_PWRBUTTON=y ++CONFIG_INPUT_UINPUT=y ++CONFIG_INPUT_PALMAS_PWRBUTTON=y ++CONFIG_RMI4_F34=y ++CONFIG_RMI4_F3A=y ++CONFIG_RMI4_F55=y ++# CONFIG_LEGACY_PTYS is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++# CONFIG_SERIAL_8250_16550A_VARIANTS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_DMA is not set ++CONFIG_SERIAL_8250_NR_UARTS=6 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=6 ++CONFIG_SERIAL_8250_OMAP=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_MAX3100=m ++CONFIG_SERIAL_MAX310X=m ++CONFIG_N_GSM=m ++CONFIG_RPMSG_TTY=m ++CONFIG_SERIAL_DEV_BUS=y ++CONFIG_TTY_PRINTK=m ++CONFIG_VIRTIO_CONSOLE=m ++CONFIG_HW_RANDOM_VIRTIO=m ++CONFIG_TCG_TIS_I2C_ATMEL=y ++CONFIG_TCG_TIS_I2C_INFINEON=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_ARB_GPIO_CHALLENGE=m ++CONFIG_I2C_MUX_GPIO=y ++CONFIG_I2C_MUX_PCA954x=m ++CONFIG_I2C_MUX_PINCTRL=y ++CONFIG_I2C_GPIO=y ++CONFIG_I2C_DIOLAN_U2C=m ++CONFIG_I2C_ROBOTFUZZ_OSIF=m ++CONFIG_I2C_TAOS_EVM=m ++CONFIG_I2C_TINY_USB=m ++CONFIG_I2C_SLAVE=y ++CONFIG_I2C_SLAVE_EEPROM=y ++CONFIG_SPI=y ++CONFIG_SPI_GPIO=y ++CONFIG_SPI_OMAP24XX=y ++CONFIG_SPI_TI_QSPI=y ++CONFIG_SPI_SPIDEV=m ++CONFIG_SPI_SLAVE=y ++CONFIG_SPI_SLAVE_TIME=m ++CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m ++CONFIG_PPS_CLIENT_LDISC=m ++CONFIG_PPS_CLIENT_GPIO=m ++CONFIG_PINCTRL_MCP23S08=m ++CONFIG_PINCTRL_PALMAS=y ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_GPIO_SYSFS=y ++CONFIG_GPIO_GENERIC_PLATFORM=y ++CONFIG_GPIO_SYSCON=y ++CONFIG_GPIO_ADNP=m ++CONFIG_GPIO_MAX7300=m ++CONFIG_GPIO_MAX732X=m ++CONFIG_GPIO_PCA953X=y ++CONFIG_GPIO_PCA953X_IRQ=y ++CONFIG_GPIO_PCF857X=m ++CONFIG_GPIO_TPIC2810=m ++CONFIG_GPIO_PALMAS=y ++CONFIG_GPIO_STMPE=y ++CONFIG_GPIO_TPS65218=y ++CONFIG_GPIO_74X164=m ++CONFIG_GPIO_MAX3191X=m ++CONFIG_GPIO_MAX7301=m ++CONFIG_GPIO_MC33880=m ++CONFIG_GPIO_PISOSR=m ++CONFIG_GPIO_XRA1403=m ++CONFIG_GPIO_AGGREGATOR=m ++CONFIG_W1=y ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2405=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2413=m ++CONFIG_W1_SLAVE_DS2406=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2805=m ++CONFIG_W1_SLAVE_DS2430=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2433_CRC=y ++CONFIG_W1_SLAVE_DS2438=m ++CONFIG_W1_SLAVE_DS250X=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_DS2781=m ++CONFIG_W1_SLAVE_DS28E04=m ++CONFIG_W1_SLAVE_DS28E17=m ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_GPIO=y ++CONFIG_POWER_RESET_GPIO_RESTART=y ++CONFIG_POWER_RESET_RESTART=y ++CONFIG_POWER_RESET_SYSCON=y ++CONFIG_POWER_RESET_SYSCON_POWEROFF=y ++CONFIG_SYSCON_REBOOT_MODE=m ++CONFIG_GENERIC_ADC_BATTERY=m ++CONFIG_BATTERY_DS2760=m ++CONFIG_CHARGER_GPIO=m ++CONFIG_CHARGER_BQ2415X=m ++CONFIG_SENSORS_AD7314=m ++CONFIG_SENSORS_AD7414=m ++CONFIG_SENSORS_AD7418=m ++CONFIG_SENSORS_ADM1025=m ++CONFIG_SENSORS_ADM1026=m ++CONFIG_SENSORS_ADM1029=m ++CONFIG_SENSORS_ADM1031=m ++CONFIG_SENSORS_ADM1177=m ++CONFIG_SENSORS_ADM9240=m ++CONFIG_SENSORS_ADT7310=m ++CONFIG_SENSORS_ADT7410=m ++CONFIG_SENSORS_ADT7411=m ++CONFIG_SENSORS_ADT7462=m ++CONFIG_SENSORS_ADT7470=m ++CONFIG_SENSORS_ADT7475=m ++CONFIG_SENSORS_AHT10=m ++CONFIG_SENSORS_AQUACOMPUTER_D5NEXT=m ++CONFIG_SENSORS_AS370=m ++CONFIG_SENSORS_ASC7621=m ++CONFIG_SENSORS_AXI_FAN_CONTROL=m ++CONFIG_SENSORS_ATXP1=m ++CONFIG_SENSORS_CORSAIR_CPRO=m ++CONFIG_SENSORS_CORSAIR_PSU=m ++CONFIG_SENSORS_DRIVETEMP=m ++CONFIG_SENSORS_DS620=m ++CONFIG_SENSORS_DS1621=m ++CONFIG_SENSORS_F71805F=m ++CONFIG_SENSORS_F71882FG=m ++CONFIG_SENSORS_F75375S=m ++CONFIG_SENSORS_FTSTEUTATES=m ++CONFIG_SENSORS_GL518SM=m ++CONFIG_SENSORS_GL520SM=m ++CONFIG_SENSORS_G760A=m ++CONFIG_SENSORS_G762=m ++CONFIG_SENSORS_GPIO_FAN=y ++CONFIG_SENSORS_HIH6130=m ++CONFIG_SENSORS_IIO_HWMON=m ++CONFIG_SENSORS_IT87=m ++CONFIG_SENSORS_JC42=m ++CONFIG_SENSORS_POWR1220=m ++CONFIG_SENSORS_LINEAGE=m ++CONFIG_SENSORS_LTC2945=m ++CONFIG_SENSORS_LTC2947_I2C=m ++CONFIG_SENSORS_LTC2947_SPI=m ++CONFIG_SENSORS_LTC2990=m ++CONFIG_SENSORS_LTC2992=m ++CONFIG_SENSORS_LTC4151=m ++CONFIG_SENSORS_LTC4215=m ++CONFIG_SENSORS_LTC4222=m ++CONFIG_SENSORS_LTC4245=m ++CONFIG_SENSORS_LTC4260=m ++CONFIG_SENSORS_LTC4261=m ++CONFIG_SENSORS_MAX1111=m ++CONFIG_SENSORS_MAX127=m ++CONFIG_SENSORS_MAX16065=m ++CONFIG_SENSORS_MAX1619=m ++CONFIG_SENSORS_MAX1668=m ++CONFIG_SENSORS_MAX197=m ++CONFIG_SENSORS_MAX31722=m ++CONFIG_SENSORS_MAX31730=m ++CONFIG_SENSORS_MAX31760=m ++CONFIG_SENSORS_MAX6620=m ++CONFIG_SENSORS_MAX6621=m ++CONFIG_SENSORS_MAX6639=m ++CONFIG_SENSORS_MAX6650=m ++CONFIG_SENSORS_MAX6697=m ++CONFIG_SENSORS_MAX31790=m ++CONFIG_SENSORS_MCP3021=m ++CONFIG_SENSORS_TC654=m ++CONFIG_SENSORS_TPS23861=m ++CONFIG_SENSORS_MR75203=m ++CONFIG_SENSORS_ADCXX=m ++CONFIG_SENSORS_LM63=m ++CONFIG_SENSORS_LM70=m ++CONFIG_SENSORS_LM73=m ++CONFIG_SENSORS_LM75=m ++CONFIG_SENSORS_LM77=m ++CONFIG_SENSORS_LM78=m ++CONFIG_SENSORS_LM80=m ++CONFIG_SENSORS_LM83=m ++CONFIG_SENSORS_LM85=m ++CONFIG_SENSORS_LM87=m ++CONFIG_SENSORS_LM90=m ++CONFIG_SENSORS_LM92=m ++CONFIG_SENSORS_LM93=m ++CONFIG_SENSORS_LM95234=m ++CONFIG_SENSORS_LM95241=m ++CONFIG_SENSORS_LM95245=m ++CONFIG_SENSORS_PC87360=m ++CONFIG_SENSORS_PC87427=m ++CONFIG_SENSORS_NTC_THERMISTOR=m ++CONFIG_SENSORS_NCT6683=m ++CONFIG_SENSORS_NCT6775_I2C=m ++CONFIG_SENSORS_NCT7802=m ++CONFIG_SENSORS_NCT7904=m ++CONFIG_SENSORS_NPCM7XX=m ++CONFIG_SENSORS_NZXT_KRAKEN2=m ++CONFIG_SENSORS_NZXT_SMART2=m ++CONFIG_SENSORS_OCC_P8_I2C=m ++CONFIG_SENSORS_PCF8591=m ++CONFIG_PMBUS=m ++CONFIG_SENSORS_ADM1266=m ++CONFIG_SENSORS_ADM1275=m ++CONFIG_SENSORS_IBM_CFFPS=m ++CONFIG_SENSORS_INSPUR_IPSPS=m ++CONFIG_SENSORS_IR35221=m ++CONFIG_SENSORS_IR38064=m ++CONFIG_SENSORS_IRPS5401=m ++CONFIG_SENSORS_ISL68137=m ++CONFIG_SENSORS_LM25066=m ++CONFIG_SENSORS_LTC2978=m ++CONFIG_SENSORS_LTC2978_REGULATOR=y ++CONFIG_SENSORS_LTC3815=m ++CONFIG_SENSORS_MAX16064=m ++CONFIG_SENSORS_MAX16601=m ++CONFIG_SENSORS_MAX20730=m ++CONFIG_SENSORS_MAX20751=m ++CONFIG_SENSORS_MAX31785=m ++CONFIG_SENSORS_MAX34440=m ++CONFIG_SENSORS_MAX8688=m ++CONFIG_SENSORS_MP2975=m ++CONFIG_SENSORS_PXE1610=m ++CONFIG_SENSORS_TPS40422=m ++CONFIG_SENSORS_TPS53679=m ++CONFIG_SENSORS_UCD9000=m ++CONFIG_SENSORS_UCD9200=m ++CONFIG_SENSORS_XDPE122=m ++CONFIG_SENSORS_ZL6100=m ++CONFIG_SENSORS_PWM_FAN=m ++CONFIG_SENSORS_SBTSI=m ++CONFIG_SENSORS_SBRMI=m ++CONFIG_SENSORS_SHT15=m ++CONFIG_SENSORS_SHT21=m ++CONFIG_SENSORS_SHT3x=m ++CONFIG_SENSORS_SHT4x=m ++CONFIG_SENSORS_SHTC1=m ++CONFIG_SENSORS_DME1737=m ++CONFIG_SENSORS_EMC1403=m ++CONFIG_SENSORS_EMC2103=m ++CONFIG_SENSORS_EMC2305=m ++CONFIG_SENSORS_EMC6W201=m ++CONFIG_SENSORS_SMSC47M1=m ++CONFIG_SENSORS_SMSC47M192=m ++CONFIG_SENSORS_SMSC47B397=m ++CONFIG_SENSORS_SCH5627=m ++CONFIG_SENSORS_SCH5636=m ++CONFIG_SENSORS_STTS751=m ++CONFIG_SENSORS_ADC128D818=m ++CONFIG_SENSORS_ADS7828=m ++CONFIG_SENSORS_ADS7871=m ++CONFIG_SENSORS_AMC6821=m ++CONFIG_SENSORS_INA209=m ++CONFIG_SENSORS_INA2XX=m ++CONFIG_SENSORS_INA238=m ++CONFIG_SENSORS_INA3221=m ++CONFIG_SENSORS_TC74=m ++CONFIG_SENSORS_THMC50=m ++CONFIG_SENSORS_TMP102=m ++CONFIG_SENSORS_TMP103=m ++CONFIG_SENSORS_TMP108=m ++CONFIG_SENSORS_TMP401=m ++CONFIG_SENSORS_TMP421=m ++CONFIG_SENSORS_TMP464=m ++CONFIG_SENSORS_TMP513=m ++CONFIG_SENSORS_VT1211=m ++CONFIG_SENSORS_W83773G=m ++CONFIG_SENSORS_W83781D=m ++CONFIG_SENSORS_W83791D=m ++CONFIG_SENSORS_W83792D=m ++CONFIG_SENSORS_W83793=m ++CONFIG_SENSORS_W83795=m ++CONFIG_SENSORS_W83795_FANCTRL=y ++CONFIG_SENSORS_W83L785TS=m ++CONFIG_SENSORS_W83L786NG=m ++CONFIG_SENSORS_W83627HF=m ++CONFIG_SENSORS_W83627EHF=m ++CONFIG_THERMAL_STATISTICS=y ++CONFIG_THERMAL_GOV_FAIR_SHARE=y ++CONFIG_THERMAL_GOV_BANG_BANG=y ++CONFIG_THERMAL_GOV_USER_SPACE=y ++CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y ++CONFIG_CPU_THERMAL=y ++CONFIG_DEVFREQ_THERMAL=y ++CONFIG_THERMAL_EMULATION=y ++CONFIG_TI_THERMAL=y ++CONFIG_OMAP5_THERMAL=y ++CONFIG_DRA752_THERMAL=y ++CONFIG_GENERIC_ADC_THERMAL=m ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_SYSFS=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=m ++CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP=y ++CONFIG_SOFT_WATCHDOG=y ++CONFIG_OMAP_WATCHDOG=y ++CONFIG_MFD_STMPE=y ++CONFIG_MFD_TI_AM335X_TSCADC=y ++CONFIG_MFD_PALMAS=y ++CONFIG_MFD_TPS65217=y ++CONFIG_MFD_TPS65218=y ++CONFIG_MFD_TPS65219=y ++CONFIG_MFD_TPS6594_I2C=y ++CONFIG_MFD_TPS6594_SPI=y ++CONFIG_MFD_WL1273_CORE=m ++CONFIG_REGULATOR_USERSPACE_CONSUMER=y ++CONFIG_REGULATOR_GPIO=y ++CONFIG_REGULATOR_PALMAS=y ++CONFIG_REGULATOR_PBIAS=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_REGULATOR_TI_ABB=y ++CONFIG_REGULATOR_TPS65217=y ++CONFIG_REGULATOR_TPS65218=y ++CONFIG_REGULATOR_TPS65219=y ++CONFIG_RC_CORE=m ++CONFIG_LIRC=y ++CONFIG_RC_DECODERS=y ++CONFIG_IR_IMON_DECODER=m ++CONFIG_IR_JVC_DECODER=m ++CONFIG_IR_MCE_KBD_DECODER=m ++CONFIG_IR_NEC_DECODER=m ++CONFIG_IR_RC5_DECODER=m ++CONFIG_IR_RC6_DECODER=m ++CONFIG_IR_SANYO_DECODER=m ++CONFIG_IR_SHARP_DECODER=m ++CONFIG_IR_SONY_DECODER=m ++CONFIG_IR_XMP_DECODER=m ++CONFIG_RC_DEVICES=y ++CONFIG_IR_GPIO_CIR=m ++CONFIG_IR_IGORPLUGUSB=m ++CONFIG_IR_IGUANA=m ++CONFIG_IR_IMON=m ++CONFIG_IR_IMON_RAW=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_IR_TTUSBIR=m ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_USB_PULSE8_CEC=m ++CONFIG_USB_RAINSHADOW_CEC=m ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_MEDIA_SUBDRV_AUTOSELECT=y ++CONFIG_MEDIA_USB_SUPPORT=y ++CONFIG_USB_GSPCA=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_DTCS033=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_JL2005BCD=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STK1135=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TOPRO=m ++CONFIG_USB_GSPCA_TOUPTEK=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_PWC=m ++CONFIG_USB_S2255=m ++CONFIG_VIDEO_USBTV=m ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_VIDEO_GO7007=m ++CONFIG_VIDEO_GO7007_USB=m ++CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_STK1160=m ++CONFIG_VIDEO_AU0828=m ++CONFIG_VIDEO_AU0828_RC=y ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_DVB_AS102=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m ++CONFIG_DVB_USB_V2=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_AF9035=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_AZ6007=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_DVBSKY=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_MXL111SF=m ++CONFIG_DVB_USB_RTL28XXU=m ++CONFIG_DVB_USB_ZD1301=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_PCTV452E=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_V4L2=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_USB_AIRSPY=m ++CONFIG_USB_HACKRF=m ++CONFIG_USB_MSI2500=m ++CONFIG_RADIO_SHARK=m ++CONFIG_RADIO_SHARK2=m ++CONFIG_RADIO_SI4713=m ++CONFIG_USB_KEENE=m ++CONFIG_USB_MA901=m ++CONFIG_USB_MR800=m ++CONFIG_USB_RAREMONO=m ++CONFIG_RADIO_SI470X=m ++CONFIG_USB_SI470X=m ++CONFIG_I2C_SI4713=m ++CONFIG_RADIO_WL128X=m ++CONFIG_V4L_PLATFORM_DRIVERS=y ++CONFIG_V4L_MEM2MEM_DRIVERS=y ++CONFIG_VIDEO_MUX=m ++CONFIG_VIDEO_WAVE_VPU=m ++CONFIG_VIDEO_TI_VPE=m ++CONFIG_SMS_SDIO_DRV=m ++CONFIG_VIDEO_IMX219=m ++CONFIG_VIDEO_IMX290=m ++CONFIG_VIDEO_MT9P031=m ++CONFIG_VIDEO_OV5640=m ++CONFIG_VIDEO_OV5645=m ++CONFIG_VIDEO_OV5647=m ++CONFIG_VIDEO_OV7251=m ++CONFIG_VIDEO_OV7670=m ++CONFIG_VIDEO_CS3308=m ++CONFIG_VIDEO_CS5345=m ++CONFIG_VIDEO_TDA7432=m ++CONFIG_VIDEO_TDA9840=m ++CONFIG_VIDEO_TEA6415C=m ++CONFIG_VIDEO_TEA6420=m ++CONFIG_VIDEO_TLV320AIC23B=m ++CONFIG_VIDEO_TVAUDIO=m ++CONFIG_VIDEO_VP27SMPX=m ++CONFIG_VIDEO_WM8739=m ++CONFIG_VIDEO_SAA6588=m ++CONFIG_VIDEO_BT819=m ++CONFIG_VIDEO_BT856=m ++CONFIG_VIDEO_KS0127=m ++CONFIG_VIDEO_SAA7110=m ++CONFIG_VIDEO_VPX3220=m ++CONFIG_VIDEO_SAA717X=m ++CONFIG_VIDEO_ADV7170=m ++CONFIG_VIDEO_ADV7175=m ++CONFIG_VIDEO_SAA7127=m ++CONFIG_VIDEO_SAA7185=m ++CONFIG_VIDEO_UPD64031A=m ++CONFIG_VIDEO_UPD64083=m ++CONFIG_VIDEO_SAA6752HS=m ++CONFIG_VIDEO_M52790=m ++CONFIG_CXD2880_SPI_DRV=m ++CONFIG_MEDIA_TUNER_M88RS6000T=m ++CONFIG_MEDIA_TUNER_MT2131=m ++CONFIG_MEDIA_TUNER_MXL301RF=m ++CONFIG_MEDIA_TUNER_QM1D1B0004=m ++CONFIG_DVB_MXL5XX=m ++CONFIG_DVB_STV0910=m ++CONFIG_DVB_STV6111=m ++CONFIG_DVB_CX24110=m ++CONFIG_DVB_CX24117=m ++CONFIG_DVB_MB86A16=m ++CONFIG_DVB_TDA8083=m ++CONFIG_DVB_TDA8261=m ++CONFIG_DVB_TUA6100=m ++CONFIG_DVB_VES1X93=m ++CONFIG_DVB_ZL10036=m ++CONFIG_DVB_CX22700=m ++CONFIG_DVB_DIB9000=m ++CONFIG_DVB_L64781=m ++CONFIG_DVB_S5H1432=m ++CONFIG_DVB_SP887X=m ++CONFIG_DVB_STV0367=m ++CONFIG_DVB_TDA10021=m ++CONFIG_DVB_VES1820=m ++CONFIG_DVB_OR51132=m ++CONFIG_DVB_OR51211=m ++CONFIG_DVB_MN88443X=m ++CONFIG_DVB_ASCOT2E=m ++CONFIG_DVB_HELENE=m ++CONFIG_DVB_HORUS3A=m ++CONFIG_DVB_ISL6405=m ++CONFIG_DVB_LGS8GL5=m ++CONFIG_DVB_LNBH25=m ++CONFIG_DVB_LNBH29=m ++CONFIG_DVB_TDA665x=m ++CONFIG_DVB_CXD2099=m ++CONFIG_DVB_DUMMY_FE=m ++CONFIG_AUXDISPLAY=y ++CONFIG_HD44780=m ++CONFIG_IMG_ASCII_LCD=m ++CONFIG_HT16K33=m ++CONFIG_LCD2S=m ++CONFIG_DRM=y ++CONFIG_DRM_LOAD_EDID_FIRMWARE=y ++CONFIG_DRM_DP_AUX_CHARDEV=y ++CONFIG_DRM_I2C_NXP_TDA998X=y ++CONFIG_DRM_VGEM=m ++CONFIG_DRM_UDL=m ++CONFIG_DRM_OMAP=y ++CONFIG_OMAP5_DSS_HDMI=y ++CONFIG_DRM_TILCDC=y ++CONFIG_DRM_PANEL_SIMPLE=y ++CONFIG_DRM_PANEL_LG_LB035Q02=m ++CONFIG_DRM_PANEL_NEC_NL8048HL11=m ++CONFIG_DRM_PANEL_ORISETECH_OTM8009A=y ++CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS=y ++CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m ++CONFIG_DRM_PANEL_SONY_ACX565AKM=m ++CONFIG_DRM_PANEL_TPO_TD028TTEC1=m ++CONFIG_DRM_PANEL_TPO_TD043MTEA1=m ++CONFIG_DRM_DISPLAY_CONNECTOR=y ++CONFIG_DRM_ITE_IT66121=m ++CONFIG_DRM_LVDS_CODEC=y ++CONFIG_DRM_SII902X=y ++CONFIG_DRM_SIMPLE_BRIDGE=m ++CONFIG_DRM_TOSHIBA_TC358767=y ++CONFIG_DRM_TOSHIBA_TC358768=y ++CONFIG_DRM_TI_TFP410=y ++CONFIG_DRM_TI_TPD12S015=y ++CONFIG_DRM_I2C_ADV7511=y ++CONFIG_DRM_I2C_ADV7511_AUDIO=y ++CONFIG_DRM_ETNAVIV=y ++CONFIG_DRM_GM12U320=m ++CONFIG_TINYDRM_HX8357D=m ++CONFIG_TINYDRM_ILI9225=m ++CONFIG_TINYDRM_ILI9341=m ++CONFIG_TINYDRM_ILI9486=m ++CONFIG_TINYDRM_MI0283QT=m ++CONFIG_TINYDRM_REPAPER=m ++CONFIG_TINYDRM_ST7586=m ++CONFIG_TINYDRM_ST7735R=m ++CONFIG_DRM_TIDSS=y ++CONFIG_DRM_LEGACY=y ++CONFIG_FB=y ++CONFIG_FB_SMSCUFX=m ++CONFIG_FB_UDL=m ++CONFIG_FB_SIMPLE=y ++CONFIG_FB_SSD1307=y ++CONFIG_FIRMWARE_EDID=y ++CONFIG_FB_TILEBLITTING=y ++CONFIG_LCD_CLASS_DEVICE=y ++CONFIG_LCD_PLATFORM=y ++CONFIG_BACKLIGHT_PWM=y ++CONFIG_BACKLIGHT_GPIO=y ++CONFIG_BACKLIGHT_LED=y ++CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION=y ++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_CLUT224 is not set ++CONFIG_SOUND=m ++CONFIG_SND=m ++CONFIG_SND_OSSEMUL=y ++CONFIG_SND_MIXER_OSS=m ++CONFIG_SND_PCM_OSS=m ++CONFIG_SND_HRTIMER=m ++CONFIG_SND_DYNAMIC_MINORS=y ++CONFIG_SND_SEQUENCER=m ++CONFIG_SND_SEQ_DUMMY=m ++CONFIG_SND_DUMMY=m ++CONFIG_SND_ALOOP=m ++CONFIG_SND_VIRMIDI=m ++CONFIG_SND_MTPAV=m ++CONFIG_SND_SERIAL_U16550=m ++CONFIG_SND_MPU401=m ++CONFIG_SND_HDA_PREALLOC_SIZE=2048 ++CONFIG_SND_USB_AUDIO=m ++CONFIG_SND_USB_UA101=m ++CONFIG_SND_USB_CAIAQ=m ++CONFIG_SND_USB_CAIAQ_INPUT=y ++CONFIG_SND_USB_6FIRE=m ++CONFIG_SND_USB_HIFACE=m ++CONFIG_SND_BCD2000=m ++CONFIG_SND_USB_POD=m ++CONFIG_SND_USB_PODHD=m ++CONFIG_SND_USB_TONEPORT=m ++CONFIG_SND_USB_VARIAX=m ++CONFIG_SND_SOC=m ++CONFIG_SND_SOC_DAVINCI_MCASP=m ++CONFIG_SND_SOC_OMAP_DMIC=m ++CONFIG_SND_SOC_OMAP_MCBSP=m ++CONFIG_SND_SOC_OMAP_MCPDM=m ++CONFIG_SND_SOC_OMAP_HDMI=m ++CONFIG_SND_SOC_ADAU1701=m ++CONFIG_SND_SOC_ADAU7002=m ++CONFIG_SND_SOC_AK4554=m ++CONFIG_SND_SOC_CS42L51_I2C=m ++CONFIG_SND_SOC_CS4265=m ++CONFIG_SND_SOC_CS4271_I2C=m ++CONFIG_SND_SOC_DMIC=m ++CONFIG_SND_SOC_ES8328_I2C=m ++CONFIG_SND_SOC_ES8328_SPI=m ++CONFIG_SND_SOC_MAX98357A=m ++CONFIG_SND_SOC_PCM3168A_I2C=m ++CONFIG_SND_SOC_PCM5102A=m ++CONFIG_SND_SOC_PCM512x_I2C=m ++CONFIG_SND_SOC_SGTL5000=m ++CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m ++CONFIG_SND_SOC_SPDIF=m ++CONFIG_SND_SOC_TLV320AIC23_I2C=m ++CONFIG_SND_SOC_TLV320AIC31XX=m ++CONFIG_SND_SOC_TS3A227E=m ++CONFIG_SND_SOC_WM8753=m ++CONFIG_SND_SOC_WM8804_I2C=m ++CONFIG_SND_SOC_WM8903=m ++CONFIG_SND_SOC_WM8904=m ++CONFIG_SND_SOC_WM8960=m ++CONFIG_SND_SOC_TPA6130A2=m ++CONFIG_SND_SIMPLE_CARD=m ++CONFIG_SND_AUDIO_GRAPH_CARD=m ++CONFIG_HID_BATTERY_STRENGTH=y ++CONFIG_HIDRAW=y ++CONFIG_UHID=y ++CONFIG_HID_A4TECH=m ++CONFIG_HID_ACCUTOUCH=m ++CONFIG_HID_ACRUX=m ++CONFIG_HID_ACRUX_FF=y ++CONFIG_HID_APPLE=m ++CONFIG_HID_ASUS=m ++CONFIG_HID_AUREAL=m ++CONFIG_HID_BELKIN=m ++CONFIG_HID_BETOP_FF=m ++CONFIG_HID_BIGBEN_FF=m ++CONFIG_HID_CHERRY=m ++CONFIG_HID_CHICONY=m ++CONFIG_HID_CORSAIR=m ++CONFIG_HID_COUGAR=m ++CONFIG_HID_MACALLY=m ++CONFIG_HID_PRODIKEYS=m ++CONFIG_HID_CMEDIA=m ++CONFIG_HID_CP2112=m ++CONFIG_HID_CREATIVE_SB0540=m ++CONFIG_HID_CYPRESS=m ++CONFIG_HID_DRAGONRISE=m ++CONFIG_DRAGONRISE_FF=y ++CONFIG_HID_EMS_FF=m ++CONFIG_HID_ELAN=m ++CONFIG_HID_ELECOM=m ++CONFIG_HID_ELO=m ++CONFIG_HID_EZKEY=m ++CONFIG_HID_FT260=m ++CONFIG_HID_GEMBIRD=m ++CONFIG_HID_GFRM=m ++CONFIG_HID_GLORIOUS=m ++CONFIG_HID_HOLTEK=m ++CONFIG_HOLTEK_FF=y ++CONFIG_HID_VIVALDI=m ++CONFIG_HID_GT683R=m ++CONFIG_HID_KEYTOUCH=m ++CONFIG_HID_KYE=m ++CONFIG_HID_UCLOGIC=m ++CONFIG_HID_WALTOP=m ++CONFIG_HID_VIEWSONIC=m ++CONFIG_HID_GYRATION=m ++CONFIG_HID_ICADE=m ++CONFIG_HID_ITE=m ++CONFIG_HID_JABRA=m ++CONFIG_HID_TWINHAN=m ++CONFIG_HID_KENSINGTON=m ++CONFIG_HID_LCPOWER=m ++CONFIG_HID_LENOVO=m ++CONFIG_HID_LOGITECH=y ++CONFIG_HID_LOGITECH_DJ=y ++CONFIG_LOGITECH_FF=y ++CONFIG_LOGIRUMBLEPAD2_FF=y ++CONFIG_LOGIG940_FF=y ++CONFIG_HID_MAGICMOUSE=m ++CONFIG_HID_MALTRON=m ++CONFIG_HID_MAYFLASH=m ++CONFIG_HID_REDRAGON=m ++CONFIG_HID_MICROSOFT=m ++CONFIG_HID_MONTEREY=m ++CONFIG_HID_MULTITOUCH=m ++CONFIG_HID_NINTENDO=m ++CONFIG_NINTENDO_FF=y ++CONFIG_HID_NTI=m ++CONFIG_HID_NTRIG=m ++CONFIG_HID_ORTEK=m ++CONFIG_HID_PANTHERLORD=m ++CONFIG_PANTHERLORD_FF=y ++CONFIG_HID_PENMOUNT=m ++CONFIG_HID_PETALYNX=m ++CONFIG_HID_PICOLCD=m ++CONFIG_HID_PICOLCD_FB=y ++CONFIG_HID_PICOLCD_BACKLIGHT=y ++CONFIG_HID_PICOLCD_LEDS=y ++CONFIG_HID_PICOLCD_CIR=y ++CONFIG_HID_PLANTRONICS=m ++CONFIG_HID_PLAYSTATION=m ++CONFIG_PLAYSTATION_FF=y ++CONFIG_HID_PRIMAX=m ++CONFIG_HID_RETRODE=m ++CONFIG_HID_ROCCAT=m ++CONFIG_HID_SAITEK=m ++CONFIG_HID_SAMSUNG=m ++CONFIG_HID_SEMITEK=m ++CONFIG_HID_SONY=m ++CONFIG_SONY_FF=y ++CONFIG_HID_SPEEDLINK=m ++CONFIG_HID_STEAM=m ++CONFIG_HID_STEELSERIES=m ++CONFIG_HID_SUNPLUS=m ++CONFIG_HID_RMI=m ++CONFIG_HID_GREENASIA=m ++CONFIG_GREENASIA_FF=y ++CONFIG_HID_SMARTJOYPLUS=m ++CONFIG_SMARTJOYPLUS_FF=y ++CONFIG_HID_TIVO=m ++CONFIG_HID_TOPSEED=m ++CONFIG_HID_THINGM=m ++CONFIG_HID_THRUSTMASTER=m ++CONFIG_THRUSTMASTER_FF=y ++CONFIG_HID_UDRAW_PS3=m ++CONFIG_HID_U2FZERO=m ++CONFIG_HID_WACOM=m ++CONFIG_HID_WIIMOTE=m ++CONFIG_HID_XINMO=m ++CONFIG_HID_ZEROPLUS=m ++CONFIG_ZEROPLUS_FF=y ++CONFIG_HID_ZYDACRON=m ++CONFIG_HID_SENSOR_HUB=m ++CONFIG_HID_SENSOR_CUSTOM_SENSOR=m ++CONFIG_HID_ALPS=m ++CONFIG_HID_MCP2221=m ++CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++CONFIG_USB_LED_TRIG=y ++CONFIG_USB_ULPI_BUS=m ++CONFIG_USB_CONN_GPIO=m ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_DYNAMIC_MINORS=y ++CONFIG_USB_OTG=y ++CONFIG_USB_LEDS_TRIGGER_USBPORT=m ++CONFIG_USB_MON=m ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++CONFIG_USB_PRINTER=m ++CONFIG_USB_TMC=m ++CONFIG_USB_STORAGE=m ++CONFIG_USB_STORAGE_REALTEK=m ++CONFIG_USB_STORAGE_DATAFAB=m ++CONFIG_USB_STORAGE_FREECOM=m ++CONFIG_USB_STORAGE_ISD200=m ++CONFIG_USB_STORAGE_USBAT=m ++CONFIG_USB_STORAGE_SDDR09=m ++CONFIG_USB_STORAGE_SDDR55=m ++CONFIG_USB_STORAGE_JUMPSHOT=m ++CONFIG_USB_STORAGE_ALAUDA=m ++CONFIG_USB_STORAGE_ONETOUCH=m ++CONFIG_USB_STORAGE_KARMA=m ++CONFIG_USB_STORAGE_CYPRESS_ATACB=m ++CONFIG_USB_STORAGE_ENE_UB6250=m ++CONFIG_USB_UAS=m ++CONFIG_USB_MDC800=m ++CONFIG_USB_MICROTEK=m ++CONFIG_USBIP_CORE=m ++CONFIG_USBIP_VHCI_HCD=m ++CONFIG_USBIP_VHCI_HC_PORTS=15 ++CONFIG_USBIP_VHCI_NR_HCS=8 ++CONFIG_USBIP_HOST=m ++CONFIG_USBIP_VUDC=m ++CONFIG_USB_MUSB_HDRC=y ++CONFIG_USB_MUSB_DSPS=y ++CONFIG_MUSB_PIO_ONLY=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_SIMPLE=m ++CONFIG_USB_SERIAL_AIRCABLE=m ++CONFIG_USB_SERIAL_ARK3116=m ++CONFIG_USB_SERIAL_BELKIN=m ++CONFIG_USB_SERIAL_CH341=m ++CONFIG_USB_SERIAL_WHITEHEAT=m ++CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m ++CONFIG_USB_SERIAL_CP210X=m ++CONFIG_USB_SERIAL_CYPRESS_M8=m ++CONFIG_USB_SERIAL_EMPEG=m ++CONFIG_USB_SERIAL_FTDI_SIO=m ++CONFIG_USB_SERIAL_VISOR=m ++CONFIG_USB_SERIAL_IPAQ=m ++CONFIG_USB_SERIAL_IR=m ++CONFIG_USB_SERIAL_EDGEPORT=m ++CONFIG_USB_SERIAL_EDGEPORT_TI=m ++CONFIG_USB_SERIAL_F81232=m ++CONFIG_USB_SERIAL_F8153X=m ++CONFIG_USB_SERIAL_GARMIN=m ++CONFIG_USB_SERIAL_IPW=m ++CONFIG_USB_SERIAL_IUU=m ++CONFIG_USB_SERIAL_KEYSPAN_PDA=m ++CONFIG_USB_SERIAL_KEYSPAN=m ++CONFIG_USB_SERIAL_KLSI=m ++CONFIG_USB_SERIAL_KOBIL_SCT=m ++CONFIG_USB_SERIAL_MCT_U232=m ++CONFIG_USB_SERIAL_METRO=m ++CONFIG_USB_SERIAL_MOS7720=m ++CONFIG_USB_SERIAL_MOS7840=m ++CONFIG_USB_SERIAL_MXUPORT=m ++CONFIG_USB_SERIAL_NAVMAN=m ++CONFIG_USB_SERIAL_PL2303=m ++CONFIG_USB_SERIAL_OTI6858=m ++CONFIG_USB_SERIAL_QCAUX=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_SERIAL_SPCP8X5=m ++CONFIG_USB_SERIAL_SAFE=m ++CONFIG_USB_SERIAL_SIERRAWIRELESS=m ++CONFIG_USB_SERIAL_SYMBOL=m ++CONFIG_USB_SERIAL_TI=m ++CONFIG_USB_SERIAL_CYBERJACK=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_OMNINET=m ++CONFIG_USB_SERIAL_OPTICON=m ++CONFIG_USB_SERIAL_XSENS_MT=m ++CONFIG_USB_SERIAL_WISHBONE=m ++CONFIG_USB_SERIAL_SSU100=m ++CONFIG_USB_SERIAL_QT2=m ++CONFIG_USB_SERIAL_UPD78F0730=m ++CONFIG_USB_SERIAL_XR=m ++CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_USB_EMI62=m ++CONFIG_USB_EMI26=m ++CONFIG_USB_ADUTUX=m ++CONFIG_USB_SEVSEG=m ++CONFIG_USB_LEGOTOWER=m ++CONFIG_USB_LCD=m ++CONFIG_USB_CYPRESS_CY7C63=m ++CONFIG_USB_CYTHERM=m ++CONFIG_USB_IDMOUSE=m ++CONFIG_USB_APPLEDISPLAY=m ++CONFIG_APPLE_MFI_FASTCHARGE=m ++CONFIG_USB_SISUSBVGA=m ++CONFIG_USB_LD=m ++CONFIG_USB_TRANCEVIBRATOR=m ++CONFIG_USB_IOWARRIOR=m ++CONFIG_USB_TEST=m ++CONFIG_USB_EHSET_TEST_FIXTURE=m ++CONFIG_USB_ISIGHTFW=m ++CONFIG_USB_YUREX=m ++CONFIG_USB_HSIC_USB3503=m ++CONFIG_USB_CHAOSKEY=m ++CONFIG_NOP_USB_XCEIV=y ++CONFIG_AM335X_PHY_USB=y ++CONFIG_USB_GPIO_VBUS=m ++CONFIG_USB_GADGET=y ++CONFIG_USB_GADGET_VBUS_DRAW=500 ++CONFIG_USB_DUMMY_HCD=m ++CONFIG_USB_CONFIGFS=y ++CONFIG_USB_CONFIGFS_SERIAL=y ++CONFIG_USB_CONFIGFS_ACM=y ++CONFIG_USB_CONFIGFS_OBEX=y ++CONFIG_USB_CONFIGFS_NCM=y ++CONFIG_USB_CONFIGFS_ECM=y ++CONFIG_USB_CONFIGFS_ECM_SUBSET=y ++CONFIG_USB_CONFIGFS_RNDIS=y ++CONFIG_USB_CONFIGFS_EEM=y ++CONFIG_USB_CONFIGFS_PHONET=y ++CONFIG_USB_CONFIGFS_MASS_STORAGE=y ++CONFIG_USB_CONFIGFS_F_LB_SS=y ++CONFIG_USB_CONFIGFS_F_FS=y ++CONFIG_USB_CONFIGFS_F_UAC1=y ++CONFIG_USB_CONFIGFS_F_UAC2=y ++CONFIG_USB_CONFIGFS_F_MIDI=y ++CONFIG_USB_CONFIGFS_F_HID=y ++CONFIG_USB_CONFIGFS_F_UVC=y ++CONFIG_USB_CONFIGFS_F_PRINTER=y ++CONFIG_USB_ZERO=m ++CONFIG_USB_AUDIO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_G_NCM=m ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_FUNCTIONFS=m ++CONFIG_USB_FUNCTIONFS_ETH=y ++CONFIG_USB_FUNCTIONFS_RNDIS=y ++CONFIG_USB_FUNCTIONFS_GENERIC=y ++CONFIG_USB_MASS_STORAGE=m ++CONFIG_USB_G_SERIAL=m ++CONFIG_USB_MIDI_GADGET=m ++CONFIG_USB_G_PRINTER=m ++CONFIG_USB_CDC_COMPOSITE=m ++CONFIG_USB_G_NOKIA=m ++CONFIG_USB_G_ACM_MS=m ++CONFIG_USB_G_MULTI=m ++CONFIG_USB_G_HID=m ++CONFIG_USB_G_DBGP=m ++CONFIG_USB_G_WEBCAM=m ++CONFIG_TYPEC=y ++CONFIG_TYPEC_HD3SS3220=y ++CONFIG_MMC=y ++CONFIG_PWRSEQ_SD8787=m ++CONFIG_MMC_BLOCK_MINORS=256 ++CONFIG_SDIO_UART=m ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SPI=m ++CONFIG_MMC_VUB300=m ++CONFIG_MMC_USHC=m ++CONFIG_MMC_SDHCI_OMAP=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_CLASS_MULTICOLOR=m ++CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_LP3944=m ++CONFIG_LEDS_LP55XX_COMMON=m ++CONFIG_LEDS_LP5523=m ++CONFIG_LEDS_PCA955X=m ++CONFIG_LEDS_PCA963X=m ++CONFIG_LEDS_DAC124S085=m ++CONFIG_LEDS_PWM=m ++CONFIG_LEDS_REGULATOR=m ++CONFIG_LEDS_BD2802=m ++CONFIG_LEDS_LT3593=m ++CONFIG_LEDS_TCA6507=m ++CONFIG_LEDS_SYSCON=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_DISK=y ++CONFIG_LEDS_TRIGGER_MTD=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++CONFIG_LEDS_TRIGGER_ACTIVITY=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_TRANSIENT=m ++CONFIG_LEDS_TRIGGER_CAMERA=m ++CONFIG_LEDS_TRIGGER_PANIC=y ++CONFIG_LEDS_TRIGGER_NETDEV=y ++CONFIG_LEDS_TRIGGER_PATTERN=m ++CONFIG_LEDS_TRIGGER_AUDIO=m ++CONFIG_ACCESSIBILITY=y ++CONFIG_A11Y_BRAILLE_CONSOLE=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_ABB5ZES3=y ++CONFIG_RTC_DRV_ABEOZ9=y ++CONFIG_RTC_DRV_ABX80X=y ++CONFIG_RTC_DRV_DS1307=y ++CONFIG_RTC_DRV_DS1374=y ++CONFIG_RTC_DRV_DS1374_WDT=y ++CONFIG_RTC_DRV_DS1672=y ++CONFIG_RTC_DRV_HYM8563=y ++CONFIG_RTC_DRV_MAX6900=y ++CONFIG_RTC_DRV_RS5C372=y ++CONFIG_RTC_DRV_ISL1208=y ++CONFIG_RTC_DRV_ISL12022=y ++CONFIG_RTC_DRV_ISL12026=y ++CONFIG_RTC_DRV_X1205=y ++CONFIG_RTC_DRV_PCF8523=y ++CONFIG_RTC_DRV_PCF85063=y ++CONFIG_RTC_DRV_PCF85363=y ++CONFIG_RTC_DRV_PCF8563=y ++CONFIG_RTC_DRV_PCF8583=y ++CONFIG_RTC_DRV_M41T80=y ++CONFIG_RTC_DRV_M41T80_WDT=y ++CONFIG_RTC_DRV_BQ32K=y ++CONFIG_RTC_DRV_PALMAS=y ++CONFIG_RTC_DRV_S35390A=y ++CONFIG_RTC_DRV_FM3130=y ++CONFIG_RTC_DRV_RX8010=y ++CONFIG_RTC_DRV_RX8581=y ++CONFIG_RTC_DRV_RX8025=y ++CONFIG_RTC_DRV_EM3027=y ++CONFIG_RTC_DRV_RV8803=y ++CONFIG_RTC_DRV_M41T93=y ++CONFIG_RTC_DRV_M41T94=y ++CONFIG_RTC_DRV_DS1302=y ++CONFIG_RTC_DRV_DS1305=y ++CONFIG_RTC_DRV_DS1343=y ++CONFIG_RTC_DRV_DS1347=y ++CONFIG_RTC_DRV_DS1390=y ++CONFIG_RTC_DRV_MAX6916=y ++CONFIG_RTC_DRV_R9701=y ++CONFIG_RTC_DRV_RX4581=y ++CONFIG_RTC_DRV_RS5C348=y ++CONFIG_RTC_DRV_MAX6902=y ++CONFIG_RTC_DRV_PCF2123=y ++CONFIG_RTC_DRV_MCP795=y ++CONFIG_RTC_DRV_DS3232=y ++CONFIG_RTC_DRV_PCF2127=y ++CONFIG_RTC_DRV_RV3029C2=y ++CONFIG_RTC_DRV_RX6110=y ++CONFIG_RTC_DRV_DS1286=m ++CONFIG_RTC_DRV_DS1511=m ++CONFIG_RTC_DRV_DS1553=m ++CONFIG_RTC_DRV_DS1685_FAMILY=m ++CONFIG_RTC_DRV_DS1742=m ++CONFIG_RTC_DRV_DS2404=m ++CONFIG_RTC_DRV_EFI=y ++CONFIG_RTC_DRV_STK17TA8=m ++CONFIG_RTC_DRV_M48T86=m ++CONFIG_RTC_DRV_M48T35=m ++CONFIG_RTC_DRV_M48T59=m ++CONFIG_RTC_DRV_MSM6242=m ++CONFIG_RTC_DRV_RP5C01=m ++CONFIG_RTC_DRV_OMAP=y ++CONFIG_RTC_DRV_HID_SENSOR_TIME=m ++CONFIG_DMADEVICES=y ++CONFIG_TI_CPPI41=y ++CONFIG_ASYNC_TX_DMA=y ++CONFIG_DMABUF_HEAPS=y ++CONFIG_DMABUF_HEAPS_SYSTEM=y ++CONFIG_DMABUF_HEAPS_CMA=y ++CONFIG_UIO=m ++CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_UIO_PRUSS=m ++CONFIG_VIRT_DRIVERS=y ++CONFIG_VIRTIO_BALLOON=m ++CONFIG_VIRTIO_INPUT=m ++CONFIG_VIRTIO_MMIO=m ++CONFIG_GREYBUS=m ++CONFIG_GREYBUS_BEAGLEPLAY=m ++CONFIG_GREYBUS_ES2=m ++CONFIG_STAGING=y ++CONFIG_RTLLIB=m ++CONFIG_RTL8723BS=m ++CONFIG_R8712U=m ++CONFIG_ADIS16203=m ++CONFIG_ADIS16240=m ++CONFIG_AD7816=m ++CONFIG_ADT7316=m ++CONFIG_ADT7316_I2C=m ++CONFIG_AD9832=m ++CONFIG_AD9834=m ++CONFIG_AD5933=m ++CONFIG_AD2S1210=m ++CONFIG_FB_TFT=m ++CONFIG_FB_TFT_AGM1264K_FL=m ++CONFIG_FB_TFT_BD663474=m ++CONFIG_FB_TFT_HX8340BN=m ++CONFIG_FB_TFT_HX8347D=m ++CONFIG_FB_TFT_HX8353D=m ++CONFIG_FB_TFT_HX8357D=m ++CONFIG_FB_TFT_ILI9163=m ++CONFIG_FB_TFT_ILI9320=m ++CONFIG_FB_TFT_ILI9325=m ++CONFIG_FB_TFT_ILI9340=m ++CONFIG_FB_TFT_ILI9341=m ++CONFIG_FB_TFT_ILI9481=m ++CONFIG_FB_TFT_ILI9486=m ++CONFIG_FB_TFT_PCD8544=m ++CONFIG_FB_TFT_RA8875=m ++CONFIG_FB_TFT_S6D02A1=m ++CONFIG_FB_TFT_S6D1121=m ++CONFIG_FB_TFT_SH1106=m ++CONFIG_FB_TFT_SSD1289=m ++CONFIG_FB_TFT_SSD1305=m ++CONFIG_FB_TFT_SSD1306=m ++CONFIG_FB_TFT_SSD1331=m ++CONFIG_FB_TFT_SSD1351=m ++CONFIG_FB_TFT_ST7735R=m ++CONFIG_FB_TFT_ST7789V=m ++CONFIG_FB_TFT_TINYLCD=m ++CONFIG_FB_TFT_TLS8204=m ++CONFIG_FB_TFT_UC1611=m ++CONFIG_FB_TFT_UC1701=m ++CONFIG_FB_TFT_UPD161704=m ++CONFIG_GREYBUS_AUDIO=m ++CONFIG_GREYBUS_BOOTROM=m ++CONFIG_GREYBUS_FIRMWARE=m ++CONFIG_GREYBUS_HID=m ++CONFIG_GREYBUS_LIGHT=m ++CONFIG_GREYBUS_LOG=m ++CONFIG_GREYBUS_LOOPBACK=m ++CONFIG_GREYBUS_POWER=m ++CONFIG_GREYBUS_RAW=m ++CONFIG_GREYBUS_VIBRATOR=m ++CONFIG_GREYBUS_BRIDGED_PHY=m ++CONFIG_GREYBUS_GPIO=m ++CONFIG_GREYBUS_I2C=m ++CONFIG_GREYBUS_PWM=m ++CONFIG_GREYBUS_SDIO=m ++CONFIG_GREYBUS_SPI=m ++CONFIG_GREYBUS_UART=m ++CONFIG_GREYBUS_USB=m ++CONFIG_COMMON_CLK_PALMAS=y ++CONFIG_COMMON_CLK_TI_ADPLL=y ++CONFIG_HWSPINLOCK=y ++CONFIG_HWSPINLOCK_OMAP=y ++CONFIG_OMAP2PLUS_MBOX=y ++CONFIG_OMAP_IOMMU=y ++CONFIG_REMOTEPROC=y ++CONFIG_REMOTEPROC_CDEV=y ++CONFIG_OMAP_REMOTEPROC=m ++CONFIG_WKUP_M3_RPROC=y ++CONFIG_RPMSG_CHAR=m ++CONFIG_RPMSG_CTRL=m ++CONFIG_RPMSG_VIRTIO=m ++CONFIG_SOC_TI=y ++CONFIG_AMX3_PM=m ++CONFIG_WKUP_M3_IPC=m ++CONFIG_TI_PRUSS=m ++CONFIG_PM_DEVFREQ=y ++CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y ++CONFIG_DEVFREQ_GOV_PERFORMANCE=y ++CONFIG_DEVFREQ_GOV_POWERSAVE=y ++CONFIG_DEVFREQ_GOV_USERSPACE=y ++CONFIG_DEVFREQ_GOV_PASSIVE=y ++CONFIG_PM_DEVFREQ_EVENT=y ++CONFIG_EXTCON_GPIO=y ++CONFIG_EXTCON_PALMAS=y ++CONFIG_EXTCON_USB_GPIO=y ++CONFIG_TI_EMIF=y ++CONFIG_TI_EMIF_SRAM=y ++CONFIG_IIO=y ++CONFIG_IIO_SW_DEVICE=m ++CONFIG_IIO_SW_TRIGGER=m ++CONFIG_ADIS16201=m ++CONFIG_ADIS16209=m ++CONFIG_ADXL313_I2C=m ++CONFIG_ADXL313_SPI=m ++CONFIG_ADXL345_I2C=m ++CONFIG_ADXL345_SPI=m ++CONFIG_ADXL355_I2C=m ++CONFIG_ADXL355_SPI=m ++CONFIG_ADXL367_SPI=m ++CONFIG_ADXL367_I2C=m ++CONFIG_ADXL372_SPI=m ++CONFIG_ADXL372_I2C=m ++CONFIG_BMA180=m ++CONFIG_BMA220=m ++CONFIG_BMA400=m ++CONFIG_BMC150_ACCEL=m ++CONFIG_BMI088_ACCEL=m ++CONFIG_DA280=m ++CONFIG_DA311=m ++CONFIG_DMARD06=m ++CONFIG_DMARD09=m ++CONFIG_DMARD10=m ++CONFIG_FXLS8962AF_I2C=m ++CONFIG_FXLS8962AF_SPI=m ++CONFIG_HID_SENSOR_ACCEL_3D=m ++CONFIG_IIO_KX022A_SPI=m ++CONFIG_IIO_KX022A_I2C=m ++CONFIG_KXSD9=m ++CONFIG_KXCJK1013=m ++CONFIG_MC3230=m ++CONFIG_MMA7455_I2C=m ++CONFIG_MMA7455_SPI=m ++CONFIG_MMA7660=m ++CONFIG_MMA8452=m ++CONFIG_MMA9551=m ++CONFIG_MMA9553=m ++CONFIG_MSA311=m ++CONFIG_MXC4005=m ++CONFIG_MXC6255=m ++CONFIG_SCA3000=m ++CONFIG_SCA3300=m ++CONFIG_STK8312=m ++CONFIG_STK8BA50=m ++CONFIG_AD4130=m ++CONFIG_AD7091R5=m ++CONFIG_AD7124=m ++CONFIG_AD7192=m ++CONFIG_AD7266=m ++CONFIG_AD7280=m ++CONFIG_AD7291=m ++CONFIG_AD7292=m ++CONFIG_AD7298=m ++CONFIG_AD7476=m ++CONFIG_AD7606_IFACE_PARALLEL=m ++CONFIG_AD7606_IFACE_SPI=m ++CONFIG_AD7766=m ++CONFIG_AD7768_1=m ++CONFIG_AD7780=m ++CONFIG_AD7791=m ++CONFIG_AD7793=m ++CONFIG_AD7887=m ++CONFIG_AD7923=m ++CONFIG_AD7949=m ++CONFIG_AD799X=m ++CONFIG_AD9467=m ++CONFIG_ADI_AXI_ADC=m ++CONFIG_CC10001_ADC=m ++CONFIG_ENVELOPE_DETECTOR=m ++CONFIG_HI8435=m ++CONFIG_HX711=m ++CONFIG_INA2XX_ADC=m ++CONFIG_LTC2471=m ++CONFIG_LTC2485=m ++CONFIG_LTC2496=m ++CONFIG_LTC2497=m ++CONFIG_MAX1027=m ++CONFIG_MAX11100=m ++CONFIG_MAX1118=m ++CONFIG_MAX11205=m ++CONFIG_MAX11410=m ++CONFIG_MAX1241=m ++CONFIG_MAX1363=m ++CONFIG_MAX9611=m ++CONFIG_MCP320X=m ++CONFIG_MCP3422=m ++CONFIG_MCP3911=m ++CONFIG_NAU7802=m ++CONFIG_PALMAS_GPADC=m ++CONFIG_RICHTEK_RTQ6056=m ++CONFIG_SD_ADC_MODULATOR=m ++CONFIG_STMPE_ADC=m ++CONFIG_TI_ADC081C=m ++CONFIG_TI_ADC0832=m ++CONFIG_TI_ADC084S021=m ++CONFIG_TI_ADC12138=m ++CONFIG_TI_ADC108S102=m ++CONFIG_TI_ADC128S052=m ++CONFIG_TI_ADC161S626=m ++CONFIG_TI_ADS1015=m ++CONFIG_TI_ADS7924=m ++CONFIG_TI_ADS1100=m ++CONFIG_TI_ADS7950=m ++CONFIG_TI_ADS8344=m ++CONFIG_TI_ADS8688=m ++CONFIG_TI_ADS124S08=m ++CONFIG_TI_ADS131E08=m ++CONFIG_TI_AM335X_ADC=y ++CONFIG_TI_LMP92064=m ++CONFIG_TI_TLC4541=m ++CONFIG_TI_TSC2046=m ++CONFIG_AD74115=m ++CONFIG_AD74413R=m ++CONFIG_IIO_RESCALE=m ++CONFIG_AD8366=m ++CONFIG_ADA4250=m ++CONFIG_HMC425=m ++CONFIG_AD7150=m ++CONFIG_AD7746=m ++CONFIG_ATLAS_PH_SENSOR=m ++CONFIG_ATLAS_EZO_SENSOR=m ++CONFIG_BME680=m ++CONFIG_CCS811=m ++CONFIG_IAQCORE=m ++CONFIG_PMS7003=m ++CONFIG_SCD30_CORE=m ++CONFIG_SCD30_I2C=m ++CONFIG_SCD30_SERIAL=m ++CONFIG_SCD4X=m ++CONFIG_SENSIRION_SGP30=m ++CONFIG_SENSIRION_SGP40=m ++CONFIG_SPS30_I2C=m ++CONFIG_SPS30_SERIAL=m ++CONFIG_SENSEAIR_SUNRISE_CO2=m ++CONFIG_VZ89X=m ++CONFIG_AD3552R=m ++CONFIG_AD5064=m ++CONFIG_AD5360=m ++CONFIG_AD5380=m ++CONFIG_AD5421=m ++CONFIG_AD5446=m ++CONFIG_AD5449=m ++CONFIG_AD5592R=m ++CONFIG_AD5593R=m ++CONFIG_AD5504=m ++CONFIG_AD5624R_SPI=m ++CONFIG_LTC2688=m ++CONFIG_AD5686_SPI=m ++CONFIG_AD5696_I2C=m ++CONFIG_AD5755=m ++CONFIG_AD5758=m ++CONFIG_AD5761=m ++CONFIG_AD5764=m ++CONFIG_AD5766=m ++CONFIG_AD5770R=m ++CONFIG_AD5791=m ++CONFIG_AD7293=m ++CONFIG_AD7303=m ++CONFIG_AD8801=m ++CONFIG_DPOT_DAC=m ++CONFIG_DS4424=m ++CONFIG_LTC1660=m ++CONFIG_LTC2632=m ++CONFIG_M62332=m ++CONFIG_MAX517=m ++CONFIG_MAX5522=m ++CONFIG_MAX5821=m ++CONFIG_MCP4725=m ++CONFIG_MCP4728=m ++CONFIG_MCP4922=m ++CONFIG_TI_DAC082S085=m ++CONFIG_TI_DAC5571=m ++CONFIG_TI_DAC7311=m ++CONFIG_TI_DAC7612=m ++CONFIG_AD9523=m ++CONFIG_ADF4350=m ++CONFIG_ADF4371=m ++CONFIG_ADF4377=m ++CONFIG_ADMV1013=m ++CONFIG_ADMV4420=m ++CONFIG_ADRF6780=m ++CONFIG_ADIS16080=m ++CONFIG_ADIS16130=m ++CONFIG_ADIS16136=m ++CONFIG_ADIS16260=m ++CONFIG_ADXRS290=m ++CONFIG_ADXRS450=m ++CONFIG_BMG160=m ++CONFIG_FXAS21002C=m ++CONFIG_HID_SENSOR_GYRO_3D=m ++CONFIG_MPU3050_I2C=m ++CONFIG_IIO_ST_GYRO_3AXIS=m ++CONFIG_ITG3200=m ++CONFIG_AFE4403=m ++CONFIG_AFE4404=m ++CONFIG_MAX30100=m ++CONFIG_MAX30102=m ++CONFIG_AM2315=m ++CONFIG_DHT11=m ++CONFIG_HDC100X=m ++CONFIG_HDC2010=m ++CONFIG_HID_SENSOR_HUMIDITY=m ++CONFIG_HTS221=m ++CONFIG_HTU21=m ++CONFIG_SI7005=m ++CONFIG_SI7020=m ++CONFIG_ADIS16400=m ++CONFIG_ADIS16460=m ++CONFIG_ADIS16475=m ++CONFIG_ADIS16480=m ++CONFIG_BMI160_I2C=m ++CONFIG_BMI160_SPI=m ++CONFIG_BOSCH_BNO055_SERIAL=m ++CONFIG_BOSCH_BNO055_I2C=m ++CONFIG_FXOS8700_I2C=m ++CONFIG_FXOS8700_SPI=m ++CONFIG_KMX61=m ++CONFIG_INV_ICM42600_I2C=m ++CONFIG_INV_ICM42600_SPI=m ++CONFIG_INV_MPU6050_I2C=m ++CONFIG_INV_MPU6050_SPI=m ++CONFIG_IIO_ST_LSM6DSX=m ++CONFIG_IIO_ST_LSM9DS0=m ++CONFIG_ADJD_S311=m ++CONFIG_ADUX1020=m ++CONFIG_AL3010=m ++CONFIG_AL3320A=m ++CONFIG_APDS9300=m ++CONFIG_APDS9960=m ++CONFIG_AS73211=m ++CONFIG_BH1750=m ++CONFIG_BH1780=m ++CONFIG_CM32181=m ++CONFIG_CM3232=m ++CONFIG_CM3323=m ++CONFIG_CM3605=m ++CONFIG_CM36651=m ++CONFIG_GP2AP002=m ++CONFIG_GP2AP020A00F=m ++CONFIG_SENSORS_ISL29018=m ++CONFIG_SENSORS_ISL29028=m ++CONFIG_ISL29125=m ++CONFIG_HID_SENSOR_ALS=m ++CONFIG_HID_SENSOR_PROX=m ++CONFIG_JSA1212=m ++CONFIG_ROHM_BU27008=m ++CONFIG_ROHM_BU27034=m ++CONFIG_RPR0521=m ++CONFIG_LTR501=m ++CONFIG_LTRF216A=m ++CONFIG_LV0104CS=m ++CONFIG_MAX44000=m ++CONFIG_MAX44009=m ++CONFIG_NOA1305=m ++CONFIG_OPT3001=m ++CONFIG_OPT4001=m ++CONFIG_PA12203001=m ++CONFIG_SI1133=m ++CONFIG_SI1145=m ++CONFIG_STK3310=m ++CONFIG_ST_UVIS25=m ++CONFIG_TCS3414=m ++CONFIG_TCS3472=m ++CONFIG_SENSORS_TSL2563=m ++CONFIG_TSL2583=m ++CONFIG_TSL2591=m ++CONFIG_TSL2772=m ++CONFIG_TSL4531=m ++CONFIG_US5182D=m ++CONFIG_VCNL4000=m ++CONFIG_VCNL4035=m ++CONFIG_VEML6030=m ++CONFIG_VEML6070=m ++CONFIG_VL6180=m ++CONFIG_ZOPT2201=m ++CONFIG_AK8974=m ++CONFIG_AK09911=m ++CONFIG_BMC150_MAGN_I2C=m ++CONFIG_BMC150_MAGN_SPI=m ++CONFIG_MAG3110=m ++CONFIG_HID_SENSOR_MAGNETOMETER_3D=m ++CONFIG_MMC35240=m ++CONFIG_SENSORS_HMC5843_I2C=m ++CONFIG_SENSORS_HMC5843_SPI=m ++CONFIG_SENSORS_RM3100_I2C=m ++CONFIG_SENSORS_RM3100_SPI=m ++CONFIG_TI_TMAG5273=m ++CONFIG_YAMAHA_YAS530=m ++CONFIG_IIO_MUX=m ++CONFIG_HID_SENSOR_INCLINOMETER_3D=m ++CONFIG_HID_SENSOR_DEVICE_ROTATION=m ++CONFIG_IIO_HRTIMER_TRIGGER=m ++CONFIG_IIO_INTERRUPT_TRIGGER=m ++CONFIG_IIO_TIGHTLOOP_TRIGGER=m ++CONFIG_IIO_SYSFS_TRIGGER=m ++CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE=m ++CONFIG_AD5110=m ++CONFIG_AD5272=m ++CONFIG_DS1803=m ++CONFIG_MAX5432=m ++CONFIG_MAX5481=m ++CONFIG_MAX5487=m ++CONFIG_MCP4018=m ++CONFIG_MCP4131=m ++CONFIG_MCP4531=m ++CONFIG_MCP41010=m ++CONFIG_TPL0102=m ++CONFIG_X9250=m ++CONFIG_LMP91000=m ++CONFIG_ABP060MG=m ++CONFIG_BMP280=m ++CONFIG_DLHL60D=m ++CONFIG_DPS310=m ++CONFIG_HID_SENSOR_PRESS=m ++CONFIG_HP03=m ++CONFIG_ICP10100=m ++CONFIG_MPL115_I2C=m ++CONFIG_MPL115_SPI=m ++CONFIG_MPL3115=m ++CONFIG_MPRLS0025PA=m ++CONFIG_MS5611=m ++CONFIG_MS5611_I2C=m ++CONFIG_MS5611_SPI=m ++CONFIG_MS5637=m ++CONFIG_IIO_ST_PRESS=m ++CONFIG_T5403=m ++CONFIG_HP206C=m ++CONFIG_ZPA2326=m ++CONFIG_AS3935=m ++CONFIG_IRSD200=m ++CONFIG_ISL29501=m ++CONFIG_LIDAR_LITE_V2=m ++CONFIG_MB1232=m ++CONFIG_PING=m ++CONFIG_RFD77402=m ++CONFIG_SRF04=m ++CONFIG_SX9310=m ++CONFIG_SX9324=m ++CONFIG_SX9360=m ++CONFIG_SX9500=m ++CONFIG_SRF08=m ++CONFIG_VCNL3020=m ++CONFIG_VL53L0X_I2C=m ++CONFIG_AD2S90=m ++CONFIG_AD2S1200=m ++CONFIG_LTC2983=m ++CONFIG_MAXIM_THERMOCOUPLE=m ++CONFIG_HID_SENSOR_TEMP=m ++CONFIG_MLX90614=m ++CONFIG_MLX90632=m ++CONFIG_TMP006=m ++CONFIG_TMP007=m ++CONFIG_TMP117=m ++CONFIG_TSYS01=m ++CONFIG_TSYS02D=m ++CONFIG_MAX30208=m ++CONFIG_MAX31856=m ++CONFIG_MAX31865=m ++CONFIG_PWM=y ++CONFIG_PWM_OMAP_DMTIMER=y ++CONFIG_PWM_PCA9685=y ++CONFIG_PWM_STMPE=y ++CONFIG_PWM_TIECAP=y ++CONFIG_PWM_TIEHRPWM=y ++CONFIG_RESET_TI_SYSCON=y ++CONFIG_PHY_CAN_TRANSCEIVER=m ++CONFIG_OMAP_USB2=y ++CONFIG_TI_PIPE3=y ++CONFIG_RAS=y ++CONFIG_FPGA=m ++CONFIG_ALTERA_PR_IP_CORE=m ++CONFIG_ALTERA_PR_IP_CORE_PLAT=m ++CONFIG_FPGA_MGR_ALTERA_PS_SPI=m ++CONFIG_FPGA_MGR_XILINX_SPI=m ++CONFIG_FPGA_MGR_ICE40_SPI=m ++CONFIG_FPGA_MGR_MACHXO2_SPI=m ++CONFIG_FPGA_BRIDGE=m ++CONFIG_ALTERA_FREEZE_BRIDGE=m ++CONFIG_XILINX_PR_DECOUPLER=m ++CONFIG_FPGA_REGION=m ++CONFIG_OF_FPGA_REGION=m ++CONFIG_MUX_ADG792A=m ++CONFIG_MUX_ADGS1408=m ++CONFIG_MUX_GPIO=m ++CONFIG_MUX_MMIO=m ++CONFIG_COUNTER=m ++CONFIG_INTERRUPT_CNT=m ++CONFIG_TI_ECAP_CAPTURE=m ++CONFIG_TI_EQEP=m ++CONFIG_VALIDATE_FS_PARSER=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_JFS_FS=m ++CONFIG_JFS_POSIX_ACL=y ++CONFIG_JFS_SECURITY=y ++CONFIG_GFS2_FS=m ++CONFIG_GFS2_FS_LOCKING_DLM=y ++CONFIG_BTRFS_FS=y ++CONFIG_BTRFS_FS_POSIX_ACL=y ++CONFIG_F2FS_FS=y ++CONFIG_F2FS_FS_SECURITY=y ++CONFIG_F2FS_FS_COMPRESSION=y ++CONFIG_ZONEFS_FS=m ++CONFIG_FS_ENCRYPTION=y ++CONFIG_FS_VERITY=y ++CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y ++CONFIG_FANOTIFY=y ++CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y ++CONFIG_QUOTA=y ++CONFIG_QUOTA_NETLINK_INTERFACE=y ++CONFIG_QFMT_V2=y ++CONFIG_AUTOFS_FS=y ++CONFIG_FUSE_FS=y ++CONFIG_CUSE=m ++CONFIG_VIRTIO_FS=m ++CONFIG_OVERLAY_FS=y ++CONFIG_FSCACHE=y ++CONFIG_FSCACHE_STATS=y ++CONFIG_CACHEFILES=y ++CONFIG_ISO9660_FS=m ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_UDF_FS=m ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_FAT_DEFAULT_UTF8=y ++CONFIG_EXFAT_FS=m ++CONFIG_NTFS_FS=m ++CONFIG_NTFS_RW=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_ECRYPT_FS=m ++CONFIG_ECRYPT_FS_MESSAGING=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_JFFS2_FS_XATTR=y ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_LZO=y ++CONFIG_JFFS2_RUBIN=y ++CONFIG_UBIFS_FS=y ++CONFIG_UBIFS_FS_ADVANCED_COMPR=y ++CONFIG_SQUASHFS=m ++CONFIG_SQUASHFS_FILE_DIRECT=y ++CONFIG_SQUASHFS_XATTR=y ++CONFIG_SQUASHFS_LZ4=y ++CONFIG_SQUASHFS_LZO=y ++CONFIG_SQUASHFS_XZ=y ++CONFIG_SQUASHFS_ZSTD=y ++CONFIG_ROMFS_FS=m ++CONFIG_ROMFS_BACKED_BY_BOTH=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_NFS_V4_1=y ++CONFIG_NFS_V4_2=y ++CONFIG_ROOT_NFS=y ++# CONFIG_NFS_V4_2_READ_PLUS is not set ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_NFSD_BLOCKLAYOUT=y ++CONFIG_NFSD_V4_SECURITY_LABEL=y ++CONFIG_RPCSEC_GSS_KRB5=m ++CONFIG_SUNRPC_DEBUG=y ++CONFIG_CEPH_FS=m ++CONFIG_CEPH_FSCACHE=y ++CONFIG_CEPH_FS_POSIX_ACL=y ++CONFIG_CIFS=m ++CONFIG_CIFS_UPCALL=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_DFS_UPCALL=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_SMB_SERVER=m ++CONFIG_CODA_FS=m ++CONFIG_AFS_FS=m ++CONFIG_AFS_FSCACHE=y ++CONFIG_9P_FS=m ++CONFIG_9P_FSCACHE=y ++CONFIG_9P_FS_POSIX_ACL=y ++CONFIG_9P_FS_SECURITY=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_737=m ++CONFIG_NLS_CODEPAGE_775=m ++CONFIG_NLS_CODEPAGE_850=m ++CONFIG_NLS_CODEPAGE_852=m ++CONFIG_NLS_CODEPAGE_855=m ++CONFIG_NLS_CODEPAGE_857=m ++CONFIG_NLS_CODEPAGE_860=m ++CONFIG_NLS_CODEPAGE_861=m ++CONFIG_NLS_CODEPAGE_862=m ++CONFIG_NLS_CODEPAGE_863=m ++CONFIG_NLS_CODEPAGE_864=m ++CONFIG_NLS_CODEPAGE_865=m ++CONFIG_NLS_CODEPAGE_866=m ++CONFIG_NLS_CODEPAGE_869=m ++CONFIG_NLS_CODEPAGE_936=m ++CONFIG_NLS_CODEPAGE_950=m ++CONFIG_NLS_CODEPAGE_932=m ++CONFIG_NLS_CODEPAGE_949=m ++CONFIG_NLS_CODEPAGE_874=m ++CONFIG_NLS_ISO8859_8=m ++CONFIG_NLS_CODEPAGE_1250=m ++CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=m ++CONFIG_NLS_ISO8859_2=m ++CONFIG_NLS_ISO8859_3=m ++CONFIG_NLS_ISO8859_4=m ++CONFIG_NLS_ISO8859_5=m ++CONFIG_NLS_ISO8859_6=m ++CONFIG_NLS_ISO8859_7=m ++CONFIG_NLS_ISO8859_9=m ++CONFIG_NLS_ISO8859_13=m ++CONFIG_NLS_ISO8859_14=m ++CONFIG_NLS_ISO8859_15=m ++CONFIG_NLS_KOI8_R=m ++CONFIG_NLS_KOI8_U=m ++CONFIG_NLS_MAC_ROMAN=m ++CONFIG_NLS_MAC_CELTIC=m ++CONFIG_NLS_MAC_CENTEURO=m ++CONFIG_NLS_MAC_CROATIAN=m ++CONFIG_NLS_MAC_CYRILLIC=m ++CONFIG_NLS_MAC_GAELIC=m ++CONFIG_NLS_MAC_GREEK=m ++CONFIG_NLS_MAC_ICELAND=m ++CONFIG_NLS_MAC_INUIT=m ++CONFIG_NLS_MAC_ROMANIAN=m ++CONFIG_NLS_MAC_TURKISH=m ++CONFIG_DLM=m ++CONFIG_DLM_DEBUG=y ++CONFIG_UNICODE=y ++CONFIG_KEY_DH_OPERATIONS=y ++CONFIG_SECURITY=y ++CONFIG_SECURITY_NETWORK_XFRM=y ++CONFIG_HARDENED_USERCOPY=y ++CONFIG_FORTIFY_SOURCE=y ++CONFIG_SECURITY_SELINUX=y ++CONFIG_SECURITY_TOMOYO=y ++CONFIG_SECURITY_APPARMOR=y ++CONFIG_SECURITY_YAMA=y ++CONFIG_SECURITY_LANDLOCK=y ++CONFIG_INTEGRITY_SIGNATURE=y ++CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y ++CONFIG_IMA=y ++CONFIG_IMA_SIG_TEMPLATE=y ++CONFIG_IMA_DEFAULT_HASH_SHA256=y ++CONFIG_IMA_APPRAISE=y ++CONFIG_IMA_ARCH_POLICY=y ++CONFIG_EVM=y ++CONFIG_DEFAULT_SECURITY_APPARMOR=y ++CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" ++CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y ++CONFIG_BUG_ON_DATA_CORRUPTION=y ++CONFIG_CRYPTO_USER=m ++CONFIG_CRYPTO_PCRYPT=m ++CONFIG_CRYPTO_TEST=m ++CONFIG_CRYPTO_ECRDSA=m ++CONFIG_CRYPTO_CURVE25519=m ++CONFIG_CRYPTO_AES_TI=m ++CONFIG_CRYPTO_BLOWFISH=m ++CONFIG_CRYPTO_CAMELLIA=m ++CONFIG_CRYPTO_CAST5=m ++CONFIG_CRYPTO_CAST6=m ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_SERPENT=m ++CONFIG_CRYPTO_TWOFISH=m ++CONFIG_CRYPTO_ADIANTUM=m ++CONFIG_CRYPTO_CFB=m ++CONFIG_CRYPTO_CTS=m ++CONFIG_CRYPTO_KEYWRAP=m ++CONFIG_CRYPTO_LRW=m ++CONFIG_CRYPTO_OFB=m ++CONFIG_CRYPTO_XTS=m ++CONFIG_CRYPTO_AEGIS128=m ++CONFIG_CRYPTO_CHACHA20POLY1305=m ++CONFIG_CRYPTO_CMAC=y ++CONFIG_CRYPTO_MD4=y ++CONFIG_CRYPTO_RMD160=m ++CONFIG_CRYPTO_SM3_GENERIC=m ++CONFIG_CRYPTO_VMAC=m ++CONFIG_CRYPTO_WP512=m ++CONFIG_CRYPTO_XCBC=m ++CONFIG_CRYPTO_LZ4=m ++CONFIG_CRYPTO_LZ4HC=m ++CONFIG_CRYPTO_ANSI_CPRNG=m ++CONFIG_CRYPTO_DRBG_HASH=y ++CONFIG_CRYPTO_DRBG_CTR=y ++CONFIG_CRYPTO_USER_API_HASH=y ++CONFIG_CRYPTO_USER_API_SKCIPHER=y ++CONFIG_CRYPTO_USER_API_RNG=m ++CONFIG_CRYPTO_USER_API_AEAD=m ++# CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set ++CONFIG_CRYPTO_GHASH_ARM_CE=m ++CONFIG_CRYPTO_NHPOLY1305_NEON=m ++CONFIG_CRYPTO_BLAKE2B_NEON=m ++CONFIG_CRYPTO_SHA1_ARM_NEON=m ++CONFIG_CRYPTO_SHA1_ARM_CE=m ++CONFIG_CRYPTO_SHA2_ARM_CE=m ++CONFIG_CRYPTO_SHA512_ARM=m ++CONFIG_CRYPTO_AES_ARM=m ++CONFIG_CRYPTO_AES_ARM_BS=m ++CONFIG_CRYPTO_AES_ARM_CE=m ++CONFIG_CRYPTO_CRC32_ARM_CE=m ++CONFIG_CRYPTO_CRCT10DIF_ARM_CE=m ++CONFIG_CRYPTO_DEV_OMAP=y ++CONFIG_CRYPTO_DEV_OMAP_SHAM=y ++CONFIG_CRYPTO_DEV_OMAP_AES=y ++CONFIG_CRYPTO_DEV_OMAP_DES=y ++CONFIG_CRYPTO_DEV_ATMEL_ECC=y ++CONFIG_CRYPTO_DEV_ATMEL_SHA204A=y ++CONFIG_CRYPTO_DEV_VIRTIO=m ++CONFIG_PKCS8_PRIVATE_KEY_PARSER=m ++# CONFIG_RAID6_PQ_BENCHMARK is not set ++CONFIG_CORDIC=m ++CONFIG_CRC4=m ++# CONFIG_XZ_DEC_X86 is not set ++# CONFIG_XZ_DEC_POWERPC is not set ++# CONFIG_XZ_DEC_IA64 is not set ++# CONFIG_XZ_DEC_SPARC is not set ++CONFIG_CMA_SIZE_MBYTES=48 ++CONFIG_IRQ_POLL=y ++CONFIG_FONTS=y ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++CONFIG_FONT_TER16x32=y ++CONFIG_PRINTK_TIME=y ++CONFIG_BOOT_PRINTK_DELAY=y ++CONFIG_DYNAMIC_DEBUG=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x01b6 ++CONFIG_PAGE_EXTENSION=y ++CONFIG_PAGE_POISONING=y ++CONFIG_DEBUG_WX=y ++CONFIG_SCHED_STACK_END_CHECK=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_SOFTLOCKUP_DETECTOR=y ++CONFIG_SCHEDSTATS=y ++CONFIG_DEBUG_PREEMPT=y ++CONFIG_DEBUG_LIST=y ++# CONFIG_RCU_TRACE is not set ++CONFIG_STACK_TRACER=y ++CONFIG_FTRACE_SYSCALLS=y ++CONFIG_TRACER_SNAPSHOT=y ++CONFIG_BLK_DEV_IO_TRACE=y ++CONFIG_HIST_TRIGGERS=y ++# CONFIG_STRICT_DEVMEM is not set ++CONFIG_NOTIFIER_ERROR_INJECTION=m ++# CONFIG_RUNTIME_TESTING_MENU is not set +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-ov5640.dtso +--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-ov5640.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-ov5640.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,77 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * ALINX AN5641 & Digilent PCam 5C - OV5640 camera module ++ * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++&{/} { ++ clk_ov5640_fixed: ov5640-xclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <12000000>; ++ }; ++}; ++ ++&main_gpio0 { ++ p11-hog { ++ /* P11 - CSI2_CAMERA_GPIO1 */ ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CSI2_CAMERA_GPIO1"; ++ }; ++}; ++ ++&wkup_i2c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ov5640: camera@3c { ++ compatible = "ovti,ov5640"; ++ reg = <0x3c>; ++ ++ clocks = <&clk_ov5640_fixed>; ++ clock-names = "xclk"; ++ ++ port { ++ csi2_cam0: endpoint { ++ remote-endpoint = <&csi2rx0_in_sensor>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++&cdns_csi2rx0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "okay"; ++ ++ csi2rx0_in_sensor: endpoint { ++ remote-endpoint = <&csi2_cam0>; ++ bus-type = <4>; /* CSI2 DPHY. */ ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++&dphy0 { ++ status = "okay"; ++}; ++ ++&ti_csi2rx0 { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-tevi-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-tevi-ov5640.dtso +--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-tevi-ov5640.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-tevi-ov5640.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,77 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Technexion TEVI-OV5640-*-RPI - OV5640 camera module ++ * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++&{/} { ++ clk_ov5640_fixed: ov5640-xclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ }; ++}; ++ ++&main_gpio0 { ++ p11-hog { ++ /* P11 - CSI2_CAMERA_GPIO1 */ ++ gpio-hog; ++ gpios = <11 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "CSI2_CAMERA_GPIO1"; ++ }; ++}; ++ ++&wkup_i2c0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ ov5640: camera@3c { ++ compatible = "ovti,ov5640"; ++ reg = <0x3c>; ++ ++ clocks = <&clk_ov5640_fixed>; ++ clock-names = "xclk"; ++ ++ port { ++ csi2_cam0: endpoint { ++ remote-endpoint = <&csi2rx0_in_sensor>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++&cdns_csi2rx0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "okay"; ++ ++ csi2rx0_in_sensor: endpoint { ++ remote-endpoint = <&csi2_cam0>; ++ bus-type = <4>; /* CSI2 DPHY. */ ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++&dphy0 { ++ status = "okay"; ++}; ++ ++&ti_csi2rx0 { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts +--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -1,9 +1,9 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * https://beagleplay.org/ + * +- * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/ +- * Copyright (C) 2022-2023 Robert Nelson, BeagleBoard.org Foundation ++ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2022-2024 Robert Nelson, BeagleBoard.org Foundation + */ + + /dts-v1/; +@@ -30,10 +30,12 @@ + i2c4 = &wkup_i2c0; + i2c5 = &mcu_i2c0; + mdio-gpio0 = &mdio0; ++ mikrobus0 = &mikrobus0; + mmc0 = &sdhci0; + mmc1 = &sdhci1; + mmc2 = &sdhci2; + rtc0 = &rtc; ++ rtc1 = &wkup_rtc0; + serial0 = &main_uart5; + serial1 = &main_uart6; + serial2 = &main_uart0; +@@ -43,9 +45,12 @@ + + chosen { + stdout-path = "serial2:115200n8"; ++ base_dtb = "k3-am625-beagleplay.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; + }; + + memory@80000000 { ++ bootph-pre-ram; + device_type = "memory"; + /* 2G RAM */ + reg = <0x00000000 0x80000000 0x00000000 0x80000000>; +@@ -83,6 +88,7 @@ + }; + + vsys_5v0: regulator-1 { ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vsys_5v0"; + regulator-min-microvolt = <5000000>; +@@ -93,6 +99,7 @@ + + vdd_3v3: regulator-2 { + /* output of TLV62595DMQR-U12 */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vdd_3v3"; + regulator-min-microvolt = <3300000>; +@@ -109,7 +116,8 @@ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; +- regulator-always-on; ++ /* regulator-always-on; */ ++ regulator-off-in-suspend; + vin-supply = <&vdd_3v3>; + gpio = <&main_gpio0 38 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; +@@ -118,6 +126,7 @@ + + vdd_3v3_sd: regulator-4 { + /* output of TPS22918DBVR-U21 */ ++ bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&vdd_3v3_sd_pins_default>; + +@@ -132,6 +141,7 @@ + }; + + vdd_sd_dv: regulator-5 { ++ bootph-all; + compatible = "regulator-gpio"; + regulator-name = "sd_hs200_switch"; + pinctrl-names = "default"; +@@ -146,9 +156,12 @@ + }; + + leds { ++ bootph-all; + compatible = "gpio-leds"; + + led-0 { ++ bootph-all; ++ label = "beaglebone:green:usr0"; + gpios = <&main_gpio0 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + function = LED_FUNCTION_HEARTBEAT; +@@ -156,6 +169,8 @@ + }; + + led-1 { ++ bootph-all; ++ label = "beaglebone:green:usr1"; + gpios = <&main_gpio0 4 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "disk-activity"; + function = LED_FUNCTION_DISK_ACTIVITY; +@@ -163,17 +178,25 @@ + }; + + led-2 { ++ bootph-all; ++ label = "beaglebone:green:usr2"; + gpios = <&main_gpio0 5 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "cpu"; + function = LED_FUNCTION_CPU; + }; + + led-3 { ++ bootph-all; ++ label = "beaglebone:green:usr3"; + gpios = <&main_gpio0 6 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_LAN; + }; + + led-4 { ++ bootph-all; ++ label = "beaglebone:green:usr4"; + gpios = <&main_gpio0 9 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "phy0tx"; + function = LED_FUNCTION_WLAN; + }; + }; +@@ -241,10 +264,38 @@ + reset-deassert-us = <60000>; /* T2 */ + }; + }; ++ ++ mikrobus0: linux-mikrobus { ++ symlink = "play/mikrobus"; ++ compatible = "linux,mikrobus"; ++ pinctrl-names = "default", "pwm_default", "pwm_gpio", ++ "uart_default", "uart_gpio", "i2c_default", ++ "i2c_gpio", "spi_default", "spi_gpio"; ++ pinctrl-0 = <&mikrobus_gpio_pins_default>; ++ pinctrl-1 = <&mikrobus_pwm_pins_default>; ++ pinctrl-2 = <&mikrobus_pwm_pins_gpio>; ++ pinctrl-3 = <&mikrobus_uart_pins_default>; ++ pinctrl-4 = <&mikrobus_uart_pins_gpio>; ++ pinctrl-5 = <&mikrobus_i2c_pins_default>; ++ pinctrl-6 = <&mikrobus_i2c_pins_gpio>; ++ pinctrl-7 = <&mikrobus_spi_pins_default>; ++ pinctrl-8 = <&mikrobus_spi_pins_gpio>; ++ i2c-adapter = <&main_i2c3>; ++ spi-master = <1>; ++ spi-cs = <0 1>; ++ uart = <&main_uart5>; ++ mikrobus-gpios = <&main_gpio1 11 GPIO_ACTIVE_HIGH>, <&main_gpio1 9 GPIO_ACTIVE_HIGH>, ++ <&main_gpio1 24 GPIO_ACTIVE_HIGH>, <&main_gpio1 25 GPIO_ACTIVE_HIGH>, ++ <&main_gpio1 22 GPIO_ACTIVE_HIGH>, <&main_gpio1 23 GPIO_ACTIVE_HIGH>, ++ <&main_gpio1 7 GPIO_ACTIVE_HIGH>, <&main_gpio1 8 GPIO_ACTIVE_HIGH>, ++ <&main_gpio1 14 GPIO_ACTIVE_HIGH>, <&main_gpio1 13 GPIO_ACTIVE_HIGH>, ++ <&main_gpio1 12 GPIO_ACTIVE_HIGH>, <&main_gpio1 10 GPIO_ACTIVE_HIGH>; ++ }; + }; + + &main_pmx0 { + gpio0_pins_default: gpio0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x0004, PIN_INPUT, 7) /* (G25) OSPI0_LBCLKO.GPIO0_1 */ + AM62X_IOPAD(0x0008, PIN_INPUT, 7) /* (J24) OSPI0_DQS.GPIO0_2 */ +@@ -264,6 +315,7 @@ + }; + + vdd_sd_dv_pins_default: vdd-sd-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x0244, PIN_OUTPUT, 7) /* (C17) MMC1_SDWP.GPIO1_49 */ + >; +@@ -283,6 +335,7 @@ + }; + + local_i2c_pins_default: local-i2c-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (B16) I2C0_SCL */ + AM62X_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (A16) I2C0_SDA */ +@@ -321,6 +374,7 @@ + }; + + emmc_pins_default: emmc-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x0220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */ + AM62X_IOPAD(0x0218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */ +@@ -336,12 +390,14 @@ + }; + + vdd_3v3_sd_pins_default: vdd-3v3-sd-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x01c4, PIN_INPUT, 7) /* (B14) SPI0_D1_GPIO1_19 */ + >; + }; + + sd_pins_default: sd-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x023c, PIN_INPUT, 0) /* (A21) MMC1_CMD */ + AM62X_IOPAD(0x0234, PIN_INPUT, 0) /* (B22) MMC1_CLK */ +@@ -401,6 +457,13 @@ + >; + }; + ++ mikrobus_i2c_pins_gpio: mikrobus-i2c-pins-gpio { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x01d0, PIN_INPUT, 7) /* (A15) UART0_CTSn.GPIO1_22 */ ++ AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */ ++ >; ++ }; ++ + mikrobus_uart_pins_default: mikrobus-uart-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01d8, PIN_INPUT, 1) /* (C15) MCAN0_TX.UART5_RXD */ +@@ -408,6 +471,13 @@ + >; + }; + ++ mikrobus_uart_pins_gpio: mikrobus-uart-pins-gpio { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x01d8, PIN_INPUT, 7) /* (C15) MCAN0_TX.GPIO1_24 */ ++ AM62X_IOPAD(0x01dc, PIN_INPUT, 7) /* (E15) MCAN0_RX.GPIO1_25 */ ++ >; ++ }; ++ + mikrobus_spi_pins_default: mikrobus-spi-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01b0, PIN_INPUT, 1) /* (A20) MCASP0_ACLKR.SPI2_CLK */ +@@ -417,7 +487,17 @@ + >; + }; + ++ mikrobus_spi_pins_gpio: mikrobus-spi-pins-gpio { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x0194, PIN_INPUT, 7) /* (B19) MCASP0_AXR3.GPIO1_7 */ ++ AM62X_IOPAD(0x0198, PIN_INPUT, 7) /* (A19) MCASP0_AXR2.GPIO1_8 */ ++ AM62X_IOPAD(0x01ac, PIN_INPUT, 7) /* (E19) MCASP0_AFSR.GPIO1_13 */ ++ AM62X_IOPAD(0x01b0, PIN_INPUT, 7) /* (A20) MCASP0_ACLKR.GPIO1_14 */ ++ >; ++ }; ++ + mikrobus_gpio_pins_default: mikrobus-gpio-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x019c, PIN_INPUT, 7) /* (B18) MCASP0_AXR1.GPIO1_9 */ + AM62X_IOPAD(0x01a0, PIN_INPUT, 7) /* (E18) MCASP0_AXR0.GPIO1_10 */ +@@ -425,13 +505,41 @@ + >; + }; + +- console_pins_default: console-default-pins { ++ main_uart0_pins_default: main-uart0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x01c8, PIN_INPUT, 0) /* (D14) UART0_RXD */ + AM62X_IOPAD(0x01cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */ + >; + }; + ++ mikrobus_pwm_pins_default: mikrobus-pwm-pins-default { ++ bootph-all; ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x01a4, PIN_INPUT, 2) /* (B20) MCASP0_ACLKX.ECAP2_IN_APWM_OUT */ ++ >; ++ }; ++ ++ mikrobus_pwm_pins_gpio: mikrobus-pwm-pins-gpio { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x01a4, PIN_INPUT, 7) /* (B20) MCASP0_ACLKX.GPIO1_11 */ ++ >; ++ }; ++ ++ touchscreen_pins_default: touchscreen-pins-default { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x01b4, PIN_OUTPUT, 7) /* (A13) SPI0_CS0.GPIO1_15 */ ++ AM62X_IOPAD(0x00a0, PIN_INPUT, 7) /* (K25) GPMC0_WPn.GPIO0_39 */ ++ >; ++ }; ++ ++ backlight_pins_default: bl-pins-default { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x0000, PIN_OUTPUT, 7) /* (H24) OSPI0_CLK.GPIO0_0 */ ++ AM62X_IOPAD(0x01b8, PIN_OUTPUT, 2) /* (C13) SPI0_CS1.EHRPWM0_B */ ++ >; ++ }; ++ + wifi_debug_uart_pins_default: wifi-debug-uart-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x001c, PIN_INPUT, 3) /* (J23) OSPI0_D4.UART6_RXD */ +@@ -544,6 +652,7 @@ + pinctrl-0 = <&i2c_csi_pins_default>; + clock-frequency = <400000>; + /* Enable with overlay for camera sensor */ ++ symlink = "play/csi/i2c"; + }; + + &mcu_i2c0 { +@@ -551,14 +660,17 @@ + pinctrl-0 = <&i2c_qwiic_pins_default>; + clock-frequency = <100000>; + status = "okay"; ++ symlink = "play/qwiic/i2c"; + }; + + &usbss0 { ++ bootph-all; + ti,vbus-divider; + status = "okay"; + }; + + &usb0 { ++ bootph-all; + dr_mode = "peripheral"; + }; + +@@ -597,6 +709,7 @@ + }; + + &main_gpio0 { ++ bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&gpio0_pins_default>; + gpio-line-names = "BL_EN_3V3", "SPE_PO_EN", "RTC_INT", /* 0-2 */ +@@ -616,6 +729,7 @@ + }; + + &main_gpio1 { ++ bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&mikrobus_gpio_pins_default>; + gpio-line-names = "", "", "", "", "", /* 0-4 */ +@@ -632,7 +746,17 @@ + "SD_CD", "SD_VOLT_SEL", "", ""; /* 48-51 */ + }; + ++&mcu_gpio0 { ++ gpio-line-names = "", "", "", "", /* 0-3 */ ++ "", "", "", "", /* 4-7 */ ++ "", "", "", "", /* 8-11 */ ++ "", "", "", "", /* 12-15 */ ++ "", "QWIIC_I2C0_SCL", "QWIIC_I2C0_SDA", "", /* 16-19 */ ++ "", "", "", ""; /* 20-23 */ ++}; ++ + &main_i2c0 { ++ bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&local_i2c_pins_default>; + clock-frequency = <400000>; +@@ -651,6 +775,7 @@ + }; + + tps65219: pmic@30 { ++ bootph-all; + compatible = "ti,tps65219"; + reg = <0x30>; + buck1-supply = <&vsys_5v0>; +@@ -742,6 +867,7 @@ + pinctrl-0 = <&grove_pins_default>; + clock-frequency = <100000>; + status = "okay"; ++ symlink = "play/grove/i2c"; + }; + + &main_i2c2 { +@@ -792,30 +918,32 @@ + pinctrl-0 = <&mikrobus_i2c_pins_default>; + clock-frequency = <400000>; + status = "okay"; ++ symlink = "play/mikrobus/i2c"; + }; + + &main_spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&mikrobus_spi_pins_default>; + status = "okay"; ++ symlink = "play/mikrobus/spi"; + }; + + &sdhci0 { ++ bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_pins_default>; +- ti,driver-strength-ohm = <50>; + disable-wp; + status = "okay"; + }; + + &sdhci1 { + /* SD/MMC */ ++ bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&sd_pins_default>; + + vmmc-supply = <&vdd_3v3_sd>; + vqmmc-supply = <&vdd_sd_dv>; +- ti,driver-strength-ohm = <50>; + disable-wp; + cd-gpios = <&main_gpio1 48 GPIO_ACTIVE_LOW>; + cd-debounce-delay-ms = <100>; +@@ -827,12 +955,10 @@ + vmmc-supply = <&wlan_en>; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_pins_default>, <&wifi_32k_clk>; +- bus-width = <4>; + non-removable; + ti,fails-without-test-cd; + cap-power-off-card; + keep-power-in-suspend; +- ti,driver-strength-ohm = <50>; + assigned-clocks = <&k3_clks 157 158>; + assigned-clock-parents = <&k3_clks 157 160>; + #address-cells = <1>; +@@ -850,8 +976,9 @@ + }; + + &main_uart0 { ++ bootph-all; + pinctrl-names = "default"; +- pinctrl-0 = <&console_pins_default>; ++ pinctrl-0 = <&main_uart0_pins_default>; + status = "okay"; + }; + +@@ -864,12 +991,21 @@ + pinctrl-names = "default"; + pinctrl-0 = <&mikrobus_uart_pins_default>; + status = "okay"; ++ symlink = "play/mikrobus/uart"; + }; + + &main_uart6 { + pinctrl-names = "default"; + pinctrl-0 = <&wifi_debug_uart_pins_default>; + status = "okay"; ++ symlink = "play/cc1352/uart"; ++ ++ mcu { ++ status = "okay"; ++ compatible = "ti,cc1352p7"; ++ reset-gpios = <&main_gpio0 72 GPIO_ACTIVE_LOW>; ++ vdds-supply = <&vdd_3v3>; ++ }; + }; + + &dss { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625.dtsi b/arch/arm64/boot/dts/ti/k3-am625.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am625.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am625.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,10 +1,10 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for AM625 SoC family in Quad core configuration + * + * TRM: https://www.ti.com/lit/pdf/spruiv7 + * +- * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2020-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + /dts-v1/; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts +--- a/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am625-phyboard-lyra-rdk.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -35,6 +35,18 @@ + standby-gpios = <&gpio_exp 1 GPIO_ACTIVE_HIGH>; + }; + ++ hdmi0: connector-hdmi { ++ compatible = "hdmi-connector"; ++ label = "hdmi"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&sii9022_out>; ++ }; ++ }; ++ }; ++ + keys { + compatible = "gpio-keys"; + autorepeat; +@@ -93,6 +105,37 @@ + >; + }; + ++ hdmi_int_pins_default: hdmi-int-default-pins { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x040, PIN_INPUT, 7) /* (N23) GPMC0_AD1.GPIO0_16 */ ++ >; ++ }; ++ ++ main_dss0_pins_default: main-dss0-default-pins { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */ ++ AM62X_IOPAD(0x0bc, PIN_OUTPUT, 0) /* (V24) VOUT0_DATA1 */ ++ AM62X_IOPAD(0x0e0, PIN_OUTPUT, 0) /* (V20) VOUT0_DATA10 */ ++ AM62X_IOPAD(0x0e4, PIN_OUTPUT, 0) /* (AA23) VOUT0_DATA11 */ ++ AM62X_IOPAD(0x0e8, PIN_OUTPUT, 0) /* (AB25) VOUT0_DATA12 */ ++ AM62X_IOPAD(0x0ec, PIN_OUTPUT, 0) /* (AA24) VOUT0_DATA13 */ ++ AM62X_IOPAD(0x0f0, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA14 */ ++ AM62X_IOPAD(0x0f4, PIN_OUTPUT, 0) /* (AA21) VOUT0_DATA15 */ ++ AM62X_IOPAD(0x0c0, PIN_OUTPUT, 0) /* (W25) VOUT0_DATA2 */ ++ AM62X_IOPAD(0x0c4, PIN_OUTPUT, 0) /* (W24) VOUT0_DATA3 */ ++ AM62X_IOPAD(0x0c8, PIN_OUTPUT, 0) /* (Y25) VOUT0_DATA4 */ ++ AM62X_IOPAD(0x0cc, PIN_OUTPUT, 0) /* (Y24) VOUT0_DATA5 */ ++ AM62X_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (Y23) VOUT0_DATA6 */ ++ AM62X_IOPAD(0x0d4, PIN_OUTPUT, 0) /* (AA25) VOUT0_DATA7 */ ++ AM62X_IOPAD(0x0d8, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA8 */ ++ AM62X_IOPAD(0x0dc, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA9 */ ++ AM62X_IOPAD(0x0fc, PIN_OUTPUT, 0) /* (Y20) VOUT0_DE */ ++ AM62X_IOPAD(0x0f8, PIN_OUTPUT, 0) /* (AB24) VOUT0_HSYNC */ ++ AM62X_IOPAD(0x104, PIN_OUTPUT, 0) /* (AC24) VOUT0_PCLK */ ++ AM62X_IOPAD(0x100, PIN_OUTPUT, 0) /* (AC25) VOUT0_VSYNC */ ++ >; ++ }; ++ + main_i2c1_pins_default: main-i2c1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */ +@@ -179,15 +222,36 @@ + cpsw3g_phy3: ethernet-phy@3 { + compatible = "ethernet-phy-id2000.a231", "ethernet-phy-ieee802.3-c22"; + reg = <3>; ++ ti,clk-output-sel = ; + ti,rx-internal-delay = ; + ti,fifo-depth = ; + }; + }; + ++&dss { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_dss0_pins_default>; ++ status = "okay"; ++}; ++ ++&dss_ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* VP2: DPI/HDMI Output */ ++ port@1 { ++ reg = <1>; ++ ++ dpi1_out: endpoint { ++ remote-endpoint = <&sii9022_in>; ++ }; ++ }; ++}; ++ + &main_i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c1_pins_default>; +- clock-frequency = <400000>; ++ clock-frequency = <100000>; + status = "okay"; + + gpio_exp: gpio-expander@21 { +@@ -201,12 +265,43 @@ + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; +- gpio-line-names = "GPIO0_HDMI_RST", "GPIO1_CAN0_nEN", ++ gpio-line-names = "", "GPIO1_CAN0_nEN", + "GPIO2_LED2", "GPIO3_LVDS_GPIO", + "GPIO4_BUT2", "GPIO5_LVDS_BKLT_EN", + "GPIO6_ETH1_USER_RESET", "GPIO7_AUDIO_USER_RESET"; + }; + ++ sii9022: bridge-hdmi@39 { ++ compatible = "sil,sii9022"; ++ reg = <0x39>; ++ ++ interrupt-parent = <&main_gpio0>; ++ interrupts = <16 IRQ_TYPE_EDGE_FALLING>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmi_int_pins_default>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ sii9022_in: endpoint { ++ remote-endpoint = <&dpi1_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ sii9022_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++ }; ++ }; ++ }; ++ + eeprom@51 { + compatible = "atmel,24c02"; + pagesize = <16>; +@@ -239,7 +334,6 @@ + vqmmc-supply = <&vddshv5_sdio>; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; +- ti,driver-strength-ohm = <50>; + disable-wp; + no-1-8-v; + status = "okay"; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk.dts b/arch/arm64/boot/dts/ti/k3-am625-sk.dts +--- a/arch/arm64/boot/dts/ti/k3-am625-sk.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am625-sk.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * AM625 SK: https://www.ti.com/lit/zip/sprr448 + * +- * Copyright (C) 2021-2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2021-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + /dts-v1/; +@@ -31,6 +31,7 @@ + + vmain_pd: regulator-0 { + /* TPS65988 PD CONTROLLER OUTPUT */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vmain_pd"; + regulator-min-microvolt = <5000000>; +@@ -41,6 +42,7 @@ + + vcc_5v0: regulator-1 { + /* Output of LM34936 */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vcc_5v0"; + regulator-min-microvolt = <5000000>; +@@ -52,6 +54,7 @@ + + vcc_3v3_sys: regulator-2 { + /* output of LM61460-Q1 */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_sys"; + regulator-min-microvolt = <3300000>; +@@ -63,6 +66,7 @@ + + vdd_mmc1: regulator-3 { + /* TPS22918DBVR */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vdd_mmc1"; + regulator-min-microvolt = <3300000>; +@@ -75,6 +79,7 @@ + + vdd_sd_dv: regulator-4 { + /* Output of TLV71033 */ ++ bootph-all; + compatible = "regulator-gpio"; + regulator-name = "tlv71033"; + pinctrl-names = "default"; +@@ -102,6 +107,7 @@ + + &main_pmx0 { + main_rgmii2_pins_default: main-rgmii2-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */ + AM62X_IOPAD(0x188, PIN_INPUT, 0) /* (AB20) RGMII2_RD1 */ +@@ -119,6 +125,7 @@ + }; + + ospi0_pins_default: ospi0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x000, PIN_OUTPUT, 0) /* (H24) OSPI0_CLK */ + AM62X_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F23) OSPI0_CSn0 */ +@@ -135,20 +142,32 @@ + }; + + vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x07c, PIN_OUTPUT, 7) /* (P25) GPMC0_CLK.GPIO0_31 */ + >; + }; + + main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */ + >; + }; + }; + ++&main_gpio0 { ++ bootph-all; ++}; ++ ++&main_gpio1 { ++ bootph-all; ++}; ++ + &main_i2c1 { ++ bootph-all; + exp1: gpio@22 { ++ bootph-all; + compatible = "ti,tca6424"; + reg = <0x22>; + gpio-controller; +@@ -207,12 +226,18 @@ + }; + }; + ++&fss { ++ bootph-all; ++}; ++ + &ospi0 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ospi0_pins_default>; + + flash@0 { ++ bootph-all; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-tx-bus-width = <8>; +@@ -225,6 +250,7 @@ + cdns,read-delay = <4>; + + partitions { ++ bootph-all; + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -260,6 +286,7 @@ + }; + + partition@3fc0000 { ++ bootph-pre-ram; + label = "ospi.phypattern"; + reg = <0x3fc0000 0x40000>; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-mallow.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-mallow.dts +--- a/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-mallow.dts 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-nonwifi-mallow.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Copyright 2023 Toradex ++ * ++ * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 ++ * https://www.toradex.com/products/carrier-board/mallow-carrier-board ++ */ ++ ++/dts-v1/; ++ ++#include "k3-am625.dtsi" ++#include "k3-am62-verdin.dtsi" ++#include "k3-am62-verdin-nonwifi.dtsi" ++#include "k3-am62-verdin-mallow.dtsi" ++ ++/ { ++ model = "Toradex Verdin AM62 on Mallow Board"; ++ compatible = "toradex,verdin-am62-nonwifi-mallow", ++ "toradex,verdin-am62-nonwifi", ++ "toradex,verdin-am62", ++ "ti,am625"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-mallow.dts b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-mallow.dts +--- a/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-mallow.dts 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am625-verdin-wifi-mallow.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Copyright 2023 Toradex ++ * ++ * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 ++ * https://www.toradex.com/products/carrier-board/mallow-carrier-board ++ */ ++ ++/dts-v1/; ++ ++#include "k3-am625.dtsi" ++#include "k3-am62-verdin.dtsi" ++#include "k3-am62-verdin-wifi.dtsi" ++#include "k3-am62-verdin-mallow.dtsi" ++ ++/ { ++ model = "Toradex Verdin AM62 WB on Mallow Board"; ++ compatible = "toradex,verdin-am62-wifi-mallow", ++ "toradex,verdin-am62-wifi", ++ "toradex,verdin-am62", ++ "ti,am625"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts +--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -20,6 +20,7 @@ + serial0 = &wkup_uart0; + serial2 = &main_uart0; + serial3 = &main_uart1; ++ mmc0 = &sdhci0; + mmc1 = &sdhci1; + }; + +@@ -79,10 +80,10 @@ + regulator-boot-on; + }; + +- vcc_3v3_sys: regulator-2 { ++ vcc_3v3_main: regulator-2 { + /* output of LM5141-Q1 */ + compatible = "regulator-fixed"; +- regulator-name = "vcc_3v3_sys"; ++ regulator-name = "vcc_3v3_main"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vmain_pd>; +@@ -101,6 +102,17 @@ + gpio = <&exp1 3 GPIO_ACTIVE_HIGH>; + }; + ++ vcc_3v3_sys: regulator-4 { ++ /* output of TPS222965DSGT */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_3v3_sys"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_3v3_main>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; +@@ -114,6 +126,53 @@ + default-state = "off"; + }; + }; ++ ++ tlv320_mclk: clk-0 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12288000>; ++ }; ++ ++ hdmi0: connector-hdmi { ++ compatible = "hdmi-connector"; ++ label = "hdmi"; ++ type = "a"; ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&sii9022_out>; ++ }; ++ }; ++ }; ++ ++ codec_audio: sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "AM62Ax-SKEVM"; ++ simple-audio-card,widgets = ++ "Headphone", "Headphone Jack", ++ "Line", "Line In", ++ "Microphone", "Microphone Jack"; ++ simple-audio-card,routing = ++ "Headphone Jack", "HPLOUT", ++ "Headphone Jack", "HPROUT", ++ "LINE1L", "Line In", ++ "LINE1R", "Line In", ++ "MIC3R", "Microphone Jack", ++ "Microphone Jack", "Mic Bias"; ++ simple-audio-card,format = "dsp_b"; ++ simple-audio-card,bitclock-master = <&sound_master>; ++ simple-audio-card,frame-master = <&sound_master>; ++ simple-audio-card,bitclock-inversion; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&mcasp1>; ++ }; ++ ++ sound_master: simple-audio-card,codec { ++ sound-dai = <&tlv320aic3106>; ++ clocks = <&tlv320_mclk>; ++ }; ++ }; + }; + + &mcu_pmx0 { +@@ -135,6 +194,39 @@ + }; + + &main_pmx0 { ++ main_dss0_pins_default: main-dss0-default-pins { ++ pinctrl-single,pins = < ++ AM62AX_IOPAD(0x100, PIN_OUTPUT, 0) /* (V17) VOUT0_VSYNC */ ++ AM62AX_IOPAD(0x0f8, PIN_OUTPUT, 0) /* (T18) VOUT0_HSYNC */ ++ AM62AX_IOPAD(0x104, PIN_OUTPUT, 0) /* (AA22) VOUT0_PCLK */ ++ AM62AX_IOPAD(0x0fc, PIN_OUTPUT, 0) /* (U17) VOUT0_DE */ ++ AM62AX_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */ ++ AM62AX_IOPAD(0x0bc, PIN_OUTPUT, 0) /* (U21) VOUT0_DATA1 */ ++ AM62AX_IOPAD(0x0c0, PIN_OUTPUT, 0) /* (U20) VOUT0_DATA2 */ ++ AM62AX_IOPAD(0x0c4, PIN_OUTPUT, 0) /* (U19) VOUT0_DATA3 */ ++ AM62AX_IOPAD(0x0c8, PIN_OUTPUT, 0) /* (T19) VOUT0_DATA4 */ ++ AM62AX_IOPAD(0x0cc, PIN_OUTPUT, 0) /* (U18) VOUT0_DATA5 */ ++ AM62AX_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (V22) VOUT0_DATA6 */ ++ AM62AX_IOPAD(0x0d4, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA7 */ ++ AM62AX_IOPAD(0x0d8, PIN_OUTPUT, 0) /* (V19) VOUT0_DATA8 */ ++ AM62AX_IOPAD(0x0dc, PIN_OUTPUT, 0) /* (V18) VOUT0_DATA9 */ ++ AM62AX_IOPAD(0x0e0, PIN_OUTPUT, 0) /* (W22) VOUT0_DATA10 */ ++ AM62AX_IOPAD(0x0e4, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA11 */ ++ AM62AX_IOPAD(0x0e8, PIN_OUTPUT, 0) /* (W20) VOUT0_DATA12 */ ++ AM62AX_IOPAD(0x0ec, PIN_OUTPUT, 0) /* (W19) VOUT0_DATA13 */ ++ AM62AX_IOPAD(0x0f0, PIN_OUTPUT, 0) /* (Y21) VOUT0_DATA14 */ ++ AM62AX_IOPAD(0x0f4, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA15 */ ++ AM62AX_IOPAD(0x05c, PIN_OUTPUT, 1) /* (P22) GPMC0_AD8.VOUT0_DATA16 */ ++ AM62AX_IOPAD(0x060, PIN_OUTPUT, 1) /* (R19) GPMC0_AD9.VOUT0_DATA17 */ ++ AM62AX_IOPAD(0x064, PIN_OUTPUT, 1) /* (R20) GPMC0_AD10.VOUT0_DATA18 */ ++ AM62AX_IOPAD(0x068, PIN_OUTPUT, 1) /* (R22) GPMC0_AD11.VOUT0_DATA19 */ ++ AM62AX_IOPAD(0x06c, PIN_OUTPUT, 1) /* (T22) GPMC0_AD12.VOUT0_DATA20 */ ++ AM62AX_IOPAD(0x070, PIN_OUTPUT, 1) /* (R21) GPMC0_AD13.VOUT0_DATA21 */ ++ AM62AX_IOPAD(0x074, PIN_OUTPUT, 1) /* (T20) GPMC0_AD14.VOUT0_DATA22 */ ++ AM62AX_IOPAD(0x078, PIN_OUTPUT, 1) /* (T21) GPMC0_AD15.VOUT0_DATA23 */ ++ >; ++ }; ++ + main_uart0_pins_default: main-uart0-default-pins { + pinctrl-single,pins = < + AM62AX_IOPAD(0x1c8, PIN_INPUT, 0) /* (E14) UART0_RXD */ +@@ -172,6 +264,22 @@ + >; + }; + ++ main_mmc0_pins_default: main-mmc0-default-pins { ++ pinctrl-single,pins = < ++ AM62AX_IOPAD(0x220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */ ++ AM62AX_IOPAD(0x218, PIN_INPUT, 0) /* (AB1) MMC0_CLKLB */ ++ AM62AX_IOPAD(0x21c, PIN_INPUT, 0) /* (AB1) MMC0_CLK */ ++ AM62AX_IOPAD(0x214, PIN_INPUT, 0) /* (AA2) MMC0_DAT0 */ ++ AM62AX_IOPAD(0x210, PIN_INPUT_PULLUP, 0) /* (AA1) MMC0_DAT1 */ ++ AM62AX_IOPAD(0x20c, PIN_INPUT_PULLUP, 0) /* (AA3) MMC0_DAT2 */ ++ AM62AX_IOPAD(0x208, PIN_INPUT_PULLUP, 0) /* (Y4) MMC0_DAT3 */ ++ AM62AX_IOPAD(0x204, PIN_INPUT_PULLUP, 0) /* (AB2) MMC0_DAT4 */ ++ AM62AX_IOPAD(0x200, PIN_INPUT_PULLUP, 0) /* (AC1) MMC0_DAT5 */ ++ AM62AX_IOPAD(0x1fc, PIN_INPUT_PULLUP, 0) /* (AD2) MMC0_DAT6 */ ++ AM62AX_IOPAD(0x1f8, PIN_INPUT_PULLUP, 0) /* (AC2) MMC0_DAT7 */ ++ >; ++ }; ++ + main_mmc1_pins_default: main-mmc1-default-pins { + pinctrl-single,pins = < + AM62AX_IOPAD(0x23c, PIN_INPUT, 0) /* (A21) MMC1_CMD */ +@@ -219,6 +327,35 @@ + AM62AX_IOPAD(0x12c, PIN_INPUT, 0) /* (W16) RGMII1_TX_CTL */ + >; + }; ++ ++ main_mcasp1_pins_default: main-mcasp1-default-pins { ++ pinctrl-single,pins = < ++ AM62AX_IOPAD(0x090, PIN_INPUT, 2) /* (L19) GPMC0_BE0n_CLE.MCASP1_ACLKX */ ++ AM62AX_IOPAD(0x098, PIN_INPUT, 2) /* (R18) GPMC0_WAIT0.MCASP1_AFSX */ ++ AM62AX_IOPAD(0x08c, PIN_OUTPUT, 2) /* (K19) GPMC0_WEn.MCASP1_AXR0 */ ++ AM62AX_IOPAD(0x084, PIN_INPUT, 2) /* (L18) GPMC0_ADVn_ALE.MCASP1_AXR2 */ ++ >; ++ }; ++ ++ main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-default-pins { ++ pinctrl-single,pins = < ++ AM62AX_IOPAD(0x01d4, PIN_INPUT, 7) /* (C15) UART0_RTSn.GPIO1_23 */ ++ >; ++ }; ++}; ++ ++&mcu_pmx0 { ++ status = "okay"; ++ ++ pmic_irq_pins_default: pmic-irq-default-pins { ++ pinctrl-single,pins = < ++ AM62AX_MCU_IOPAD(0x000, PIN_INPUT, 7) /* (E11) MCU_GPIO0_0 */ ++ >; ++ }; ++}; ++ ++&mcu_gpio0 { ++ status = "okay"; + }; + + &main_i2c0 { +@@ -244,6 +381,87 @@ + }; + }; + }; ++ ++ tps659312: pmic@48 { ++ compatible = "ti,tps6593-q1"; ++ reg = <0x48>; ++ ti,primary-pmic; ++ system-power-controller; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_irq_pins_default>; ++ interrupt-parent = <&mcu_gpio0>; ++ interrupts = <0 IRQ_TYPE_EDGE_FALLING>; ++ ++ buck123-supply = <&vcc_3v3_sys>; ++ buck4-supply = <&vcc_3v3_sys>; ++ buck5-supply = <&vcc_3v3_sys>; ++ ldo1-supply = <&vcc_3v3_sys>; ++ ldo2-supply = <&vcc_3v3_sys>; ++ ldo3-supply = <&buck5>; ++ ldo4-supply = <&vcc_3v3_sys>; ++ ++ regulators { ++ buck123: buck123 { ++ regulator-name = "vcc_core"; ++ regulator-min-microvolt = <715000>; ++ regulator-max-microvolt = <895000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buck4: buck4 { ++ regulator-name = "vcc_1v1"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buck5: buck5 { ++ regulator-name = "vcc_1v8_sys"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo1: ldo1 { ++ regulator-name = "vddshv5_sdio"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo2: ldo2 { ++ regulator-name = "vpp_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo3: ldo3 { ++ regulator-name = "vcc_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo4: ldo4 { ++ regulator-name = "vdda_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; + }; + + &main_i2c1 { +@@ -257,6 +475,12 @@ + reg = <0x22>; + gpio-controller; + #gpio-cells = <2>; ++ interrupt-parent = <&main_gpio1>; ++ interrupts = <23 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_gpio1_ioexp_intr_pins_default>; + + gpio-line-names = "GPIO_CPSW2_RST", "GPIO_CPSW1_RST", + "BT_EN_SOC", "MMC1_SD_EN", +@@ -271,6 +495,85 @@ + "MCASP1_FET_SEL", "UART1_FET_SEL", + "PD_I2C_IRQ", "IO_EXP_TEST_LED"; + }; ++ ++ tlv320aic3106: audio-codec@1b { ++ #sound-dai-cells = <0>; ++ compatible = "ti,tlv320aic3106"; ++ reg = <0x1b>; ++ ai3x-micbias-vg = <1>; /* 2.0V */ ++ ++ /* Regulators */ ++ AVDD-supply = <&vcc_3v3_sys>; ++ IOVDD-supply = <&vcc_3v3_sys>; ++ DRVDD-supply = <&vcc_3v3_sys>; ++ DVDD-supply = <&buck5>; ++ }; ++ ++ exp2: gpio@23 { ++ compatible = "ti,tca6424"; ++ reg = <0x23>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ gpio-line-names = "", "", ++ "", "", ++ "", "", ++ "", "", ++ "WL_LT_EN", "CSI_RSTz", ++ "", "", ++ "", "", ++ "", "", ++ "SPI0_FET_SEL", "SPI0_FET_OE", ++ "RGMII2_BRD_CONN_DET", "CSI_SEL2", ++ "CSI_EN", "AUTO_100M_1000M_CONFIG", ++ "CSI_VLDO_SEL", "SoC_WLAN_SDIO_RST"; ++ }; ++ ++ sii9022: bridge-hdmi@3b { ++ compatible = "sil,sii9022"; ++ reg = <0x3b>; ++ interrupt-parent = <&exp1>; ++ interrupts = <16 IRQ_TYPE_EDGE_FALLING>; ++ #sound-dai-cells = <0>; ++ sil,i2s-data-lanes = < 0 >; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ sii9022_in: endpoint { ++ remote-endpoint = <&dpi1_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ sii9022_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&main_i2c2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c2_pins_default>; ++ clock-frequency = <400000>; ++}; ++ ++&sdhci0 { ++ /* eMMC */ ++ status = "okay"; ++ non-removable; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_mmc0_pins_default>; ++ disable-wp; + }; + + &sdhci1 { +@@ -279,7 +582,6 @@ + vmmc-supply = <&vdd_mmc1>; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; +- ti,driver-strength-ohm = <50>; + disable-wp; + }; + +@@ -361,3 +663,40 @@ + ti,min-output-impedance; + }; + }; ++ ++&mcasp1 { ++ status = "okay"; ++ #sound-dai-cells = <0>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_mcasp1_pins_default>; ++ ++ op-mode = <0>; /* MCASP_IIS_MODE */ ++ tdm-slots = <2>; ++ ++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ ++ 1 0 2 0 ++ 0 0 0 0 ++ 0 0 0 0 ++ 0 0 0 0 ++ >; ++ tx-num-evt = <32>; ++ rx-num-evt = <32>; ++}; ++ ++&dss { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_dss0_pins_default>; ++}; ++ ++&dss_ports { ++ /* VP2: DPI Output */ ++ port@1 { ++ reg = <1>; ++ ++ dpi1_out: endpoint { ++ remote-endpoint = <&sii9022_in>; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -42,9 +42,8 @@ + }; + }; + +- main_conf: syscon@100000 { +- compatible = "ti,j721e-system-controller", "syscon", "simple-mfd"; +- reg = <0x00 0x00100000 0x00 0x20000>; ++ main_conf: bus@100000 { ++ compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00 0x00 0x00100000 0x20000>; +@@ -101,8 +100,13 @@ + <0x00 0x4c000000 0x00 0x20000>, + <0x00 0x4a820000 0x00 0x20000>, + <0x00 0x4aa40000 0x00 0x20000>, +- <0x00 0x4bc00000 0x00 0x100000>; +- reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt"; ++ <0x00 0x4bc00000 0x00 0x100000>, ++ <0x00 0x48600000 0x00 0x8000>, ++ <0x00 0x484a4000 0x00 0x2000>, ++ <0x00 0x484c2000 0x00 0x2000>, ++ <0x00 0x48420000 0x00 0x2000>; ++ reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "bchan"; + msi-parent = <&inta_main_dmss>; + #dma-cells = <3>; + ti,sci = <&dmsc>; +@@ -117,8 +121,13 @@ + reg = <0x00 0x485c0000 0x00 0x100>, + <0x00 0x4a800000 0x00 0x20000>, + <0x00 0x4aa00000 0x00 0x40000>, +- <0x00 0x4b800000 0x00 0x400000>; +- reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt"; ++ <0x00 0x4b800000 0x00 0x400000>, ++ <0x00 0x485e0000 0x00 0x10000>, ++ <0x00 0x484a0000 0x00 0x2000>, ++ <0x00 0x484c0000 0x00 0x2000>, ++ <0x00 0x48430000 0x00 0x1000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "rflow"; + msi-parent = <&inta_main_dmss>; + #dma-cells = <2>; + ti,sci = <&dmsc>; +@@ -144,6 +153,44 @@ + }; + }; + ++ dmss_csi: bus@4e000000 { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dma-ranges; ++ ranges = <0x00 0x4e000000 0x00 0x4e000000 0x00 0x300000>; ++ ++ ti,sci-dev-id = <198>; ++ ++ inta_main_dmss_csi: interrupt-controller@4e0a0000 { ++ compatible = "ti,sci-inta"; ++ reg = <0x00 0x4e0a0000 0x00 0x8000>; ++ #interrupt-cells = <0>; ++ interrupt-controller; ++ interrupt-parent = <&gic500>; ++ msi-controller; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <200>; ++ ti,interrupt-ranges = <0 237 8>; ++ ti,unmapped-event-sources = <&main_bcdma_csi>; ++ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>; ++ }; ++ ++ main_bcdma_csi: dma-controller@4e230000 { ++ compatible = "ti,am62a-dmss-bcdma-csirx"; ++ reg = <0x00 0x4e230000 0x00 0x100>, ++ <0x00 0x4e180000 0x00 0x8000>, ++ <0x00 0x4e100000 0x00 0x10000>; ++ reg-names = "gcfg", "rchanrt", "ringrt"; ++ msi-parent = <&inta_main_dmss_csi>; ++ #dma-cells = <3>; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <199>; ++ ti,sci-rm-range-rchan = <0x21>; ++ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>; ++ }; ++ }; ++ + dmsc: system-controller@44043000 { + compatible = "ti,k2g-sci"; + reg = <0x00 0x44043000 0x00 0xfe0>; +@@ -488,6 +535,24 @@ + status = "disabled"; + }; + ++ sdhci0: mmc@fa10000 { ++ compatible = "ti,am62-sdhci"; ++ reg = <0x00 0xfa10000 0x00 0x260>, <0x00 0xfa18000 0x00 0x134>; ++ interrupts = ; ++ power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 57 5>, <&k3_clks 57 6>; ++ clock-names = "clk_ahb", "clk_xin"; ++ assigned-clocks = <&k3_clks 57 6>; ++ assigned-clock-parents = <&k3_clks 57 8>; ++ bus-width = <8>; ++ mmc-hs200-1_8v; ++ ti,clkbuf-sel = <0x7>; ++ ti,otap-del-sel-legacy = <0x0>; ++ ti,otap-del-sel-mmc-hs = <0x0>; ++ ti,otap-del-sel-hs200 = <0x6>; ++ status = "disabled"; ++ }; ++ + sdhci1: mmc@fa00000 { + compatible = "ti,am62-sdhci"; + reg = <0x00 0xfa00000 0x00 0x260>, <0x00 0xfa08000 0x00 0x134>; +@@ -495,7 +560,8 @@ + power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 58 5>, <&k3_clks 58 6>; + clock-names = "clk_ahb", "clk_xin"; +- ti,trm-icp = <0x2>; ++ bus-width = <4>; ++ ti,clkbuf-sel = <0x7>; + ti,otap-del-sel-legacy = <0x0>; + ti,otap-del-sel-sd-hs = <0x0>; + ti,otap-del-sel-sdr12 = <0xf>; +@@ -507,8 +573,30 @@ + ti,itap-del-sel-sd-hs = <0x0>; + ti,itap-del-sel-sdr12 = <0x0>; + ti,itap-del-sel-sdr25 = <0x0>; +- ti,clkbuf-sel = <0x7>; ++ no-1-8-v; ++ status = "disabled"; ++ }; ++ ++ sdhci2: mmc@fa20000 { ++ compatible = "ti,am62-sdhci"; ++ reg = <0x00 0xfa20000 0x00 0x260>, <0x00 0xfa28000 0x00 0x134>; ++ interrupts = ; ++ power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 184 5>, <&k3_clks 184 6>; ++ clock-names = "clk_ahb", "clk_xin"; + bus-width = <4>; ++ ti,clkbuf-sel = <0x7>; ++ ti,otap-del-sel-legacy = <0x0>; ++ ti,otap-del-sel-sd-hs = <0x0>; ++ ti,otap-del-sel-sdr12 = <0xf>; ++ ti,otap-del-sel-sdr25 = <0xf>; ++ ti,otap-del-sel-sdr50 = <0xc>; ++ ti,otap-del-sel-sdr104 = <0x6>; ++ ti,otap-del-sel-ddr50 = <0x9>; ++ ti,itap-del-sel-legacy = <0x0>; ++ ti,itap-del-sel-sd-hs = <0x0>; ++ ti,itap-del-sel-sdr12 = <0x0>; ++ ti,itap-del-sel-sdr25 = <0x0>; + no-1-8-v; + status = "disabled"; + }; +@@ -816,4 +904,151 @@ + clock-names = "fck"; + status = "disabled"; + }; ++ ++ mcasp0: audio-controller@2b00000 { ++ compatible = "ti,am33xx-mcasp-audio"; ++ reg = <0x00 0x02b00000 0x00 0x2000>, ++ <0x00 0x02b08000 0x00 0x400>; ++ reg-names = "mpu", "dat"; ++ interrupts = , ++ ; ++ interrupt-names = "tx", "rx"; ++ ++ dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>; ++ dma-names = "tx", "rx"; ++ ++ clocks = <&k3_clks 190 0>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 190 0>; ++ assigned-clock-parents = <&k3_clks 190 2>; ++ power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ mcasp1: audio-controller@2b10000 { ++ compatible = "ti,am33xx-mcasp-audio"; ++ reg = <0x00 0x02b10000 0x00 0x2000>, ++ <0x00 0x02b18000 0x00 0x400>; ++ reg-names = "mpu", "dat"; ++ interrupts = , ++ ; ++ interrupt-names = "tx", "rx"; ++ ++ dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>; ++ dma-names = "tx", "rx"; ++ ++ clocks = <&k3_clks 191 0>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 191 0>; ++ assigned-clock-parents = <&k3_clks 191 2>; ++ power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ mcasp2: audio-controller@2b20000 { ++ compatible = "ti,am33xx-mcasp-audio"; ++ reg = <0x00 0x02b20000 0x00 0x2000>, ++ <0x00 0x02b28000 0x00 0x400>; ++ reg-names = "mpu", "dat"; ++ interrupts = , ++ ; ++ interrupt-names = "tx", "rx"; ++ ++ dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>; ++ dma-names = "tx", "rx"; ++ ++ clocks = <&k3_clks 192 0>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 192 0>; ++ assigned-clock-parents = <&k3_clks 192 2>; ++ power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ ti_csi2rx0: ticsi2rx@30102000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ dmas = <&main_bcdma_csi 0 0x5000 0>; ++ dma-names = "rx0"; ++ reg = <0x00 0x30102000 0x00 0x1000>; ++ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ cdns_csi2rx0: csi-bridge@30101000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x00 0x30101000 0x00 0x1000>; ++ clocks = <&k3_clks 182 0>, <&k3_clks 182 3>, <&k3_clks 182 0>, ++ <&k3_clks 182 0>, <&k3_clks 182 4>, <&k3_clks 182 4>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy0>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi0_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi0_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi0_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi0_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ dphy0: phy@30110000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x00 0x30110000 0x00 0x1100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ dss: dss@30200000 { ++ compatible = "ti,am62a7-dss"; ++ reg = <0x00 0x30200000 0x00 0x1000>, /* common */ ++ <0x00 0x30202000 0x00 0x1000>, /* vidl1 */ ++ <0x00 0x30206000 0x00 0x1000>, /* vid */ ++ <0x00 0x30207000 0x00 0x1000>, /* ovr1 */ ++ <0x00 0x30208000 0x00 0x1000>, /* ovr2 */ ++ <0x00 0x3020a000 0x00 0x1000>, /* vp1: Tied OFF in the SoC */ ++ <0x00 0x3020b000 0x00 0x1000>, /* vp2: Used as DPI Out */ ++ <0x00 0x30201000 0x00 0x1000>; /* common1 */ ++ reg-names = "common", "vidl1", "vid", ++ "ovr1", "ovr2", "vp1", "vp2", "common1"; ++ power-domains = <&k3_pds 186 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 186 6>, ++ <&k3_clks 186 0>, ++ <&k3_clks 186 2>; ++ clock-names = "fck", "vp1", "vp2"; ++ interrupts = ; ++ status = "disabled"; ++ ++ dss_ports: ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62.dtsi b/arch/arm64/boot/dts/ti/k3-am62.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for AM62 SoC Family + * +- * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2020-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +@@ -47,6 +47,7 @@ + }; + + cbass_main: bus@f0000 { ++ bootph-all; + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; +@@ -86,6 +87,7 @@ + <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>; + + cbass_mcu: bus@4000000 { ++ bootph-all; + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; +@@ -93,6 +95,7 @@ + }; + + cbass_wakeup: bus@b00000 { ++ bootph-all; + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for AM625 SoC Family Main Domain peripherals + * +- * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2020-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + &cbass_main { +@@ -42,9 +42,8 @@ + }; + }; + +- main_conf: syscon@100000 { +- compatible = "syscon", "simple-mfd"; +- reg = <0x00 0x00100000 0x00 0x20000>; ++ main_conf: bus@100000 { ++ compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x00 0x00100000 0x20000>; +@@ -81,7 +80,8 @@ + }; + + dmss: bus@48000000 { +- compatible = "simple-mfd"; ++ bootph-all; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + dma-ranges; +@@ -90,6 +90,7 @@ + ti,sci-dev-id = <25>; + + secure_proxy_main: mailbox@4d000000 { ++ bootph-all; + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; +@@ -119,8 +120,13 @@ + <0x00 0x4c000000 0x00 0x20000>, + <0x00 0x4a820000 0x00 0x20000>, + <0x00 0x4aa40000 0x00 0x20000>, +- <0x00 0x4bc00000 0x00 0x100000>; +- reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt"; ++ <0x00 0x4bc00000 0x00 0x100000>, ++ <0x00 0x48600000 0x00 0x8000>, ++ <0x00 0x484a4000 0x00 0x2000>, ++ <0x00 0x484c2000 0x00 0x2000>, ++ <0x00 0x48420000 0x00 0x2000>; ++ reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "bchan"; + msi-parent = <&inta_main_dmss>; + #dma-cells = <3>; + +@@ -136,8 +142,13 @@ + reg = <0x00 0x485c0000 0x00 0x100>, + <0x00 0x4a800000 0x00 0x20000>, + <0x00 0x4aa00000 0x00 0x40000>, +- <0x00 0x4b800000 0x00 0x400000>; +- reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt"; ++ <0x00 0x4b800000 0x00 0x400000>, ++ <0x00 0x485e0000 0x00 0x10000>, ++ <0x00 0x484a0000 0x00 0x2000>, ++ <0x00 0x484c0000 0x00 0x2000>, ++ <0x00 0x48430000 0x00 0x1000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "rflow"; + msi-parent = <&inta_main_dmss>; + #dma-cells = <2>; + +@@ -165,6 +176,7 @@ + }; + + dmsc: system-controller@44043000 { ++ bootph-all; + compatible = "ti,k2g-sci"; + ti,host-id = <12>; + mbox-names = "rx", "tx"; +@@ -174,16 +186,19 @@ + reg = <0x00 0x44043000 0x00 0xfe0>; + + k3_pds: power-controller { ++ bootph-all; + compatible = "ti,sci-pm-domain"; + #power-domain-cells = <2>; + }; + + k3_clks: clock-controller { ++ bootph-all; + compatible = "ti,k2g-sci-clk"; + #clock-cells = <2>; + }; + + k3_reset: reset-controller { ++ bootph-all; + compatible = "ti,sci-reset"; + #reset-cells = <2>; + }; +@@ -202,6 +217,7 @@ + }; + + secure_proxy_sa3: mailbox@43600000 { ++ bootph-pre-ram; + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; +@@ -217,6 +233,7 @@ + }; + + main_pmx0: pinctrl@f4000 { ++ bootph-all; + compatible = "pinctrl-single"; + reg = <0x00 0xf4000 0x00 0x2ac>; + #pinctrl-cells = <1>; +@@ -225,12 +242,14 @@ + }; + + main_esm: esm@420000 { ++ bootph-pre-ram; + compatible = "ti,j721e-esm"; + reg = <0x00 0x420000 0x00 0x1000>; + ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>; + }; + + main_timer0: timer@2400000 { ++ bootph-all; + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; +@@ -492,6 +511,9 @@ + main_gpio0: gpio@600000 { + compatible = "ti,am64-gpio", "ti,keystone-gpio"; + reg = <0x0 0x00600000 0x0 0x100>; ++ gpio-ranges = <&main_pmx0 0 0 32>, ++ <&main_pmx0 32 33 38>, ++ <&main_pmx0 70 72 22>; + gpio-controller; + #gpio-cells = <2>; + interrupt-parent = <&main_gpio_intr>; +@@ -510,6 +532,10 @@ + compatible = "ti,am64-gpio", "ti,keystone-gpio"; + reg = <0x0 0x00601000 0x0 0x100>; + gpio-controller; ++ gpio-ranges = <&main_pmx0 0 94 41>, ++ <&main_pmx0 41 136 6>, ++ <&main_pmx0 47 143 3>, ++ <&main_pmx0 50 149 2>; + #gpio-cells = <2>; + interrupt-parent = <&main_gpio_intr>; + interrupts = <180>, <181>, <182>, +@@ -532,10 +558,9 @@ + clock-names = "clk_ahb", "clk_xin"; + assigned-clocks = <&k3_clks 57 6>; + assigned-clock-parents = <&k3_clks 57 8>; ++ bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; +- ti,trm-icp = <0x2>; +- bus-width = <8>; + ti,clkbuf-sel = <0x7>; + ti,otap-del-sel-legacy = <0x0>; + ti,otap-del-sel-mmc-hs = <0x0>; +@@ -553,7 +578,8 @@ + power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 58 5>, <&k3_clks 58 6>; + clock-names = "clk_ahb", "clk_xin"; +- ti,trm-icp = <0x2>; ++ bus-width = <4>; ++ ti,clkbuf-sel = <0x7>; + ti,otap-del-sel-legacy = <0x8>; + ti,otap-del-sel-sd-hs = <0x0>; + ti,otap-del-sel-sdr12 = <0x0>; +@@ -565,8 +591,6 @@ + ti,itap-del-sel-sd-hs = <0x1>; + ti,itap-del-sel-sdr12 = <0xa>; + ti,itap-del-sel-sdr25 = <0x1>; +- ti,clkbuf-sel = <0x7>; +- bus-width = <4>; + status = "disabled"; + }; + +@@ -577,7 +601,8 @@ + power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 184 5>, <&k3_clks 184 6>; + clock-names = "clk_ahb", "clk_xin"; +- ti,trm-icp = <0x2>; ++ bus-width = <4>; ++ ti,clkbuf-sel = <0x7>; + ti,otap-del-sel-legacy = <0x8>; + ti,otap-del-sel-sd-hs = <0x0>; + ti,otap-del-sel-sdr12 = <0x0>; +@@ -589,7 +614,6 @@ + ti,itap-del-sel-sd-hs = <0xa>; + ti,itap-del-sel-sdr12 = <0xa>; + ti,itap-del-sel-sdr25 = <0x1>; +- ti,clkbuf-sel = <0x7>; + status = "disabled"; + }; + +@@ -613,6 +637,8 @@ + interrupt-names = "host", "peripheral"; + maximum-speed = "high-speed"; + dr_mode = "otg"; ++ snps,usb2-gadget-lpm-disable; ++ snps,usb2-lpm-disable; + }; + }; + +@@ -636,6 +662,8 @@ + interrupt-names = "host", "peripheral"; + maximum-speed = "high-speed"; + dr_mode = "otg"; ++ snps,usb2-gadget-lpm-disable; ++ snps,usb2-lpm-disable; + }; + }; + +@@ -665,6 +693,15 @@ + }; + }; + ++ gpu: gpu@fd00000 { ++ compatible = "ti,am62-gpu", "img,img-axe"; ++ reg = <0x00 0x0fd00000 0x00 0x20000>; ++ clocks = <&k3_clks 187 0>; ++ clock-names = "core"; ++ interrupts = ; ++ power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>; ++ }; ++ + cpsw3g: ethernet@8000000 { + compatible = "ti,am642-cpsw-nuss"; + #address-cells = <2>; +@@ -743,9 +780,10 @@ + <0x00 0x30207000 0x00 0x1000>, /* ovr1 */ + <0x00 0x30208000 0x00 0x1000>, /* ovr2 */ + <0x00 0x3020a000 0x00 0x1000>, /* vp1: Used for OLDI */ +- <0x00 0x3020b000 0x00 0x1000>; /* vp2: Used as DPI Out */ ++ <0x00 0x3020b000 0x00 0x1000>, /* vp2: Used as DPI Out */ ++ <0x00 0x30201000 0x00 0x1000>; /* common1 */ + reg-names = "common", "vidl1", "vid", +- "ovr1", "ovr2", "vp1", "vp2"; ++ "ovr1", "ovr2", "vp1", "vp2", "common1"; + power-domains = <&k3_pds 186 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 186 6>, + <&dss_vp1_clk>, +@@ -955,4 +993,66 @@ + power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>; + status = "disabled"; + }; ++ ++ ti_csi2rx0: ticsi2rx@30102000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ dmas = <&main_bcdma 0 0x4700 0>; ++ dma-names = "rx0"; ++ reg = <0x00 0x30102000 0x00 0x1000>; ++ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ cdns_csi2rx0: csi-bridge@30101000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x00 0x30101000 0x00 0x1000>; ++ clocks = <&k3_clks 182 0>, <&k3_clks 182 3>, <&k3_clks 182 0>, ++ <&k3_clks 182 0>, <&k3_clks 182 4>, <&k3_clks 182 4>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy0>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi0_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi0_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi0_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi0_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ dphy0: phy@30110000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x00 0x30110000 0x00 0x1100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,12 +1,13 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for AM625 SoC Family MCU Domain peripherals + * +- * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2020-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + &cbass_mcu { + mcu_pmx0: pinctrl@4084000 { ++ bootph-all; + compatible = "pinctrl-single"; + reg = <0x00 0x04084000 0x00 0x88>; + #pinctrl-cells = <1>; +@@ -15,6 +16,7 @@ + }; + + mcu_esm: esm@4100000 { ++ bootph-pre-ram; + compatible = "ti,j721e-esm"; + reg = <0x00 0x4100000 0x00 0x1000>; + ti,esm-pins = <0>, <1>, <2>, <85>; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5.dtsi b/arch/arm64/boot/dts/ti/k3-am62p5.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62p5.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62p5.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,7 +1,7 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree file for the AM62P5 SoC family (quad core) +- * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + * TRM: https://www.ti.com/lit/pdf/spruj83 + */ +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts +--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -8,6 +8,9 @@ + + /dts-v1/; + ++#include ++#include ++#include + #include "k3-am62p5.dtsi" + + / { +@@ -18,6 +21,12 @@ + serial0 = &wkup_uart0; + serial2 = &main_uart0; + serial3 = &main_uart1; ++ mmc0 = &sdhci0; ++ mmc1 = &sdhci1; ++ mmc2 = &sdhci2; ++ spi0 = &ospi0; ++ ethernet0 = &cpsw_port1; ++ ethernet1 = &cpsw_port2; + }; + + chosen { +@@ -29,6 +38,7 @@ + reg = <0x00000000 0x80000000 0x00000000 0x80000000>, + <0x00000008 0x80000000 0x00000001 0x80000000>; + device_type = "memory"; ++ bootph-pre-ram; + }; + + reserved-memory { +@@ -52,35 +62,514 @@ + no-map; + }; + }; ++ ++ vmain_pd: regulator-0 { ++ /* TPS65988 PD CONTROLLER OUTPUT */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vmain_pd"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ bootph-all; ++ }; ++ ++ vcc_5v0: regulator-1 { ++ /* Output of TPS630702RNMR */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_5v0"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vmain_pd>; ++ regulator-always-on; ++ regulator-boot-on; ++ bootph-all; ++ }; ++ ++ vdd_mmc1: regulator-2 { ++ /* TPS22918DBVR */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd_mmc1"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ enable-active-high; ++ gpio = <&exp1 3 GPIO_ACTIVE_HIGH>; ++ bootph-all; ++ }; ++ ++ vddshv_sdio: regulator-3 { ++ compatible = "regulator-gpio"; ++ regulator-name = "vddshv_sdio"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vddshv_sdio_pins_default>; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ gpios = <&main_gpio0 31 GPIO_ACTIVE_HIGH>; ++ states = <1800000 0x0>, ++ <3300000 0x1>; ++ bootph-all; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usr_led_pins_default>; ++ ++ led-0 { ++ label = "am62-sk:green:heartbeat"; ++ gpios = <&main_gpio1 49 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "heartbeat"; ++ function = LED_FUNCTION_HEARTBEAT; ++ default-state = "off"; ++ }; ++ }; ++ ++ tlv320_mclk: clk-0 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <12288000>; ++ }; ++ ++ codec_audio: sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "AM62x-SKEVM"; ++ simple-audio-card,widgets = ++ "Headphone", "Headphone Jack", ++ "Line", "Line In", ++ "Microphone", "Microphone Jack"; ++ simple-audio-card,routing = ++ "Headphone Jack", "HPLOUT", ++ "Headphone Jack", "HPROUT", ++ "LINE1L", "Line In", ++ "LINE1R", "Line In", ++ "MIC3R", "Microphone Jack", ++ "Microphone Jack", "Mic Bias"; ++ simple-audio-card,format = "dsp_b"; ++ simple-audio-card,bitclock-master = <&sound_master>; ++ simple-audio-card,frame-master = <&sound_master>; ++ simple-audio-card,bitclock-inversion; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&mcasp1>; ++ }; ++ ++ sound_master: simple-audio-card,codec { ++ sound-dai = <&tlv320aic3106>; ++ clocks = <&tlv320_mclk>; ++ }; ++ }; ++}; ++ ++&main_gpio0 { ++ bootph-all; ++}; ++ ++&main_gpio1 { ++ bootph-all; + }; + + &main_pmx0 { +- main_uart0_pins_default: main-uart0-default-pins { ++ bootph-all; ++ ++ main_i2c0_pins_default: main-i2c0-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (B25) I2C0_SCL */ ++ AM62PX_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (A24) I2C0_SDA */ ++ >; ++ }; ++ ++ main_i2c1_pins_default: main-i2c1-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x01e8, PIN_INPUT_PULLUP, 0) /* (C24) I2C1_SCL */ ++ AM62PX_IOPAD(0x01ec, PIN_INPUT_PULLUP, 0) /* (B24) I2C1_SDA */ ++ >; + bootph-all; ++ }; ++ ++ main_i2c2_pins_default: main-i2c2-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x00b0, PIN_INPUT_PULLUP, 1) /* (T22) GPMC0_CSn2.I2C2_SCL */ ++ AM62PX_IOPAD(0x00b4, PIN_INPUT_PULLUP, 1) /* (U25) GPMC0_CSn3.I2C2_SDA */ ++ >; ++ }; ++ ++ main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x01d4, PIN_INPUT, 7) /* (C22) UART0_RTSn.GPIO1_23 */ ++ >; ++ }; ++ ++ main_mcasp1_pins_default: main-mcasp1-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x0090, PIN_INPUT, 2) /* (U24) GPMC0_BE0n_CLE.MCASP1_ACLKX */ ++ AM62PX_IOPAD(0x0098, PIN_INPUT, 2) /* (AA24) GPMC0_WAIT0.MCASP1_AFSX */ ++ AM62PX_IOPAD(0x008c, PIN_INPUT, 2) /* (T25) GPMC0_WEn.MCASP1_AXR0 */ ++ AM62PX_IOPAD(0x0084, PIN_INPUT, 2) /* (R25) GPMC0_ADVn_ALE.MCASP1_AXR2 */ ++ >; ++ }; ++ ++ main_mdio1_pins_default: main-mdio1-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x0160, PIN_OUTPUT, 0) /* (F17) MDIO0_MDC */ ++ AM62PX_IOPAD(0x015c, PIN_INPUT, 0) /* (F16) MDIO0_MDIO */ ++ >; ++ }; ++ ++ main_mmc1_pins_default: main-mmc1-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x023c, PIN_INPUT, 0) /* (H20) MMC1_CMD */ ++ AM62PX_IOPAD(0x0234, PIN_OUTPUT, 0) /* (J24) MMC1_CLK */ ++ AM62PX_IOPAD(0x0230, PIN_INPUT, 0) /* (H21) MMC1_DAT0 */ ++ AM62PX_IOPAD(0x022c, PIN_INPUT_PULLUP, 0) /* (H23) MMC1_DAT1 */ ++ AM62PX_IOPAD(0x0228, PIN_INPUT_PULLUP, 0) /* (H22) MMC1_DAT2 */ ++ AM62PX_IOPAD(0x0224, PIN_INPUT_PULLUP, 0) /* (H25) MMC1_DAT3 */ ++ AM62PX_IOPAD(0x0240, PIN_INPUT, 0) /* (D23) MMC1_SDCD */ ++ >; ++ bootph-all; ++ }; ++ ++ main_mmc2_pins_default: main-mmc2-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x0120, PIN_INPUT, 0) /* (K24) MMC2_CMD */ ++ AM62PX_IOPAD(0x0118, PIN_OUTPUT, 0) /* (K21) MMC2_CLK */ ++ AM62PX_IOPAD(0x011C, PIN_INPUT, 0) /* () MMC2_CLKLB */ ++ AM62PX_IOPAD(0x0114, PIN_INPUT, 0) /* (K23) MMC2_DAT0 */ ++ AM62PX_IOPAD(0x0110, PIN_INPUT_PULLUP, 0) /* (K22) MMC2_DAT1 */ ++ AM62PX_IOPAD(0x010c, PIN_INPUT_PULLUP, 0) /* (L20) MMC2_DAT2 */ ++ AM62PX_IOPAD(0x0108, PIN_INPUT_PULLUP, 0) /* (L21) MMC2_DAT3 */ ++ >; ++ bootph-all; ++ }; ++ ++ main_rgmii1_pins_default: main-rgmii1-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x014c, PIN_INPUT, 0) /* (B15) RGMII1_RD0 */ ++ AM62PX_IOPAD(0x0150, PIN_INPUT, 0) /* (B16) RGMII1_RD1 */ ++ AM62PX_IOPAD(0x0154, PIN_INPUT, 0) /* (A14) RGMII1_RD2 */ ++ AM62PX_IOPAD(0x0158, PIN_INPUT, 0) /* (B14) RGMII1_RD3 */ ++ AM62PX_IOPAD(0x0148, PIN_INPUT, 0) /* (A16) RGMII1_RXC */ ++ AM62PX_IOPAD(0x0144, PIN_INPUT, 0) /* (A15) RGMII1_RX_CTL */ ++ AM62PX_IOPAD(0x0134, PIN_INPUT, 0) /* (A18) RGMII1_TD0 */ ++ AM62PX_IOPAD(0x0138, PIN_INPUT, 0) /* (C17) RGMII1_TD1 */ ++ AM62PX_IOPAD(0x013c, PIN_INPUT, 0) /* (A17) RGMII1_TD2 */ ++ AM62PX_IOPAD(0x0140, PIN_INPUT, 0) /* (C16) RGMII1_TD3 */ ++ AM62PX_IOPAD(0x0130, PIN_INPUT, 0) /* (B17) RGMII1_TXC */ ++ AM62PX_IOPAD(0x012c, PIN_INPUT, 0) /* (B18) RGMII1_TX_CTL */ ++ >; ++ bootph-all; ++ }; ++ ++ main_rgmii2_pins_default: main-rgmii2-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x0184, PIN_INPUT, 0) /* (E19) RGMII2_RD0 */ ++ AM62PX_IOPAD(0x0188, PIN_INPUT, 0) /* (E16) RGMII2_RD1 */ ++ AM62PX_IOPAD(0x018c, PIN_INPUT, 0) /* (E17) RGMII2_RD2 */ ++ AM62PX_IOPAD(0x0190, PIN_INPUT, 0) /* (C19) RGMII2_RD3 */ ++ AM62PX_IOPAD(0x0180, PIN_INPUT, 0) /* (D19) RGMII2_RXC */ ++ AM62PX_IOPAD(0x017c, PIN_INPUT, 0) /* (F19) RGMII2_RX_CTL */ ++ AM62PX_IOPAD(0x016c, PIN_INPUT, 0) /* (B19) RGMII2_TD0 */ ++ AM62PX_IOPAD(0x0170, PIN_INPUT, 0) /* (A21) RGMII2_TD1 */ ++ AM62PX_IOPAD(0x0174, PIN_INPUT, 0) /* (D17) RGMII2_TD2 */ ++ AM62PX_IOPAD(0x0178, PIN_INPUT, 0) /* (A19) RGMII2_TD3 */ ++ AM62PX_IOPAD(0x0168, PIN_INPUT, 0) /* (D16) RGMII2_TXC */ ++ AM62PX_IOPAD(0x0164, PIN_INPUT, 0) /* (A20) RGMII2_TX_CTL */ ++ >; ++ bootph-all; ++ }; ++ ++ main_uart0_pins_default: main-uart0-default-pins { + pinctrl-single,pins = < + AM62PX_IOPAD(0x1c8, PIN_INPUT, 0) /* (A22) UART0_RXD */ + AM62PX_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (B22) UART0_TXD */ +- AM62PX_IOPAD(0x1d0, PIN_INPUT, 0) /* (A23) UART0_CTSn */ +- AM62PX_IOPAD(0x1d4, PIN_OUTPUT, 0) /* (C22) UART0_RTSn */ + >; ++ bootph-all; + }; + + main_uart1_pins_default: main-uart1-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x0194, PIN_INPUT, 2) /* (D25) MCASP0_AXR3.UART1_CTSn */ ++ AM62PX_IOPAD(0x0198, PIN_OUTPUT, 2) /* (E25) MCASP0_AXR2.UART1_RTSn */ ++ AM62PX_IOPAD(0x01ac, PIN_INPUT, 2) /* (G23) MCASP0_AFSR.UART1_RXD */ ++ AM62PX_IOPAD(0x01b0, PIN_OUTPUT, 2) /* (G20) MCASP0_ACLKR.UART1_TXD */ ++ >; ++ bootph-all; ++ }; ++ ++ main_wlirq_pins_default: main-wlirq-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x0128, PIN_INPUT, 7) /* (K25) MMC2_SDWP.GPIO0_72 */ ++ >; ++ }; ++ ++ ospi0_pins_default: ospi0-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x0000, PIN_OUTPUT, 0) /* (P23) OSPI0_CLK */ ++ AM62PX_IOPAD(0x002c, PIN_OUTPUT, 0) /* (M25) OSPI0_CSn0 */ ++ AM62PX_IOPAD(0x000c, PIN_INPUT, 0) /* (L25) OSPI0_D0 */ ++ AM62PX_IOPAD(0x0010, PIN_INPUT, 0) /* (N24) OSPI0_D1 */ ++ AM62PX_IOPAD(0x0014, PIN_INPUT, 0) /* (N25) OSPI0_D2 */ ++ AM62PX_IOPAD(0x0018, PIN_INPUT, 0) /* (M24) OSPI0_D3 */ ++ AM62PX_IOPAD(0x001c, PIN_INPUT, 0) /* (N21) OSPI0_D4 */ ++ AM62PX_IOPAD(0x0020, PIN_INPUT, 0) /* (N22) OSPI0_D5 */ ++ AM62PX_IOPAD(0x0024, PIN_INPUT, 0) /* (P21) OSPI0_D6 */ ++ AM62PX_IOPAD(0x0028, PIN_INPUT, 0) /* (N20) OSPI0_D7 */ ++ AM62PX_IOPAD(0x0008, PIN_INPUT, 0) /* (P22) OSPI0_DQS */ ++ >; ++ bootph-all; ++ }; ++ ++ usr_led_pins_default: usr-led-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x0244, PIN_INPUT, 7) /* (D24) MMC1_SDWP.GPIO1_49 */ ++ >; ++ }; ++ ++ vddshv_sdio_pins_default: vddshvr-sdio-default-pins { ++ pinctrl-single,pins = < ++ AM62PX_IOPAD(0x007c, PIN_INPUT, 7) /* (Y25) GPMC0_CLK.GPIO0_31 */ ++ >; + bootph-all; ++ }; ++ ++ wlan_en_pins_default: wlan-en-default-pins { + pinctrl-single,pins = < +- AM62PX_IOPAD(0x194, PIN_INPUT, 2) /* (D25) MCASP0_AXR3 */ +- AM62PX_IOPAD(0x198, PIN_OUTPUT, 2) /* (E25) MCASP0_AXR2 */ +- AM62PX_IOPAD(0x1ac, PIN_INPUT, 2) /* (G23) MCASP0_AFSR */ +- AM62PX_IOPAD(0x1b0, PIN_OUTPUT, 2) /* (G20) MCASP0_ACLKR */ ++ AM62PX_IOPAD(0x0124, PIN_INPUT, 7) /* (J25) MMC2_SDCD.GPIO0_71 */ + >; + }; + }; + +-&main_uart0 { ++&main_i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c1_pins_default>; ++ clock-frequency = <100000>; ++ bootph-all; ++ ++ tlv320aic3106: audio-codec@1b { ++ #sound-dai-cells = <0>; ++ compatible = "ti,tlv320aic3106"; ++ reg = <0x1b>; ++ ai3x-micbias-vg = <1>; /* 2.0V */ ++ }; ++ ++ exp1: gpio@22 { ++ compatible = "ti,tca6424"; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ gpio-line-names = "OLDI_INT#", "x8_NAND_DETECT", ++ "UART1_FET_SEL", "MMC1_SD_EN", ++ "VPP_EN", "EXP_PS_3V3_EN", ++ "UART1_FET_BUF_EN", "EXP_HAT_DETECT", ++ "DSI_GPIO0", "DSI_GPIO1", ++ "OLDI_EDID", "BT_UART_WAKE_SOC_3V3", ++ "USB_TYPEA_OC_INDICATION", "CSI_GPIO0", ++ "CSI_GPIO1", "WLAN_ALERTn", ++ "HDMI_INTn", "TEST_GPIO2", ++ "MCASP1_FET_EN", "MCASP1_BUF_BT_EN", ++ "MCASP1_FET_SEL", "DSI_EDID", ++ "PD_I2C_IRQ", "IO_EXP_TEST_LED"; ++ ++ interrupt-parent = <&main_gpio1>; ++ interrupts = <23 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_gpio1_ioexp_intr_pins_default>; ++ bootph-all; ++ }; ++ ++ exp2: gpio@23 { ++ compatible = "ti,tca6424"; ++ reg = <0x23>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ gpio-line-names = "BT_EN_SOC", "EXP_PS_5V0_EN", ++ "", "", ++ "", "", ++ "", "", ++ "WL_LT_EN", "", ++ "TP3", "TP6", ++ "TP4", "TP7", ++ "TP5", "TP8", ++ "SoC_I2C2_MCAN_SEL", "GPIO_HDMI_RSTn", ++ "GPIO_CPSW2_RST", "GPIO_CPSW1_RST", ++ "GPIO_OLDI_RSTn", "GPIO_AUD_RSTn", ++ "GPIO_eMMC_RSTn", "SoC_WLAN_SDIO_RST"; ++ }; ++}; ++ ++&main_i2c2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c2_pins_default>; ++ clock-frequency = <400000>; ++}; ++ ++&sdhci0 { ++ status = "okay"; ++ ti,driver-strength-ohm = <50>; ++ disable-wp; ++ bootph-all; ++}; ++ ++&sdhci1 { ++ /* SD/MMC */ ++ status = "okay"; ++ vmmc-supply = <&vdd_mmc1>; ++ vqmmc-supply = <&vddshv_sdio>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_mmc1_pins_default>; ++ disable-wp; + bootph-all; ++}; ++ ++&cpsw3g { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_rgmii1_pins_default>, ++ <&main_rgmii2_pins_default>; ++}; ++ ++&cpsw_port1 { ++ phy-mode = "rgmii-rxid"; ++ phy-handle = <&cpsw3g_phy0>; ++}; ++ ++&cpsw_port2 { ++ phy-mode = "rgmii-rxid"; ++ phy-handle = <&cpsw3g_phy1>; ++}; ++ ++&cpsw3g_mdio { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_mdio1_pins_default>; ++ status = "okay"; ++ ++ cpsw3g_phy0: ethernet-phy@0 { ++ reg = <0>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ ti,min-output-impedance; ++ }; ++ ++ cpsw3g_phy1: ethernet-phy@1 { ++ reg = <1>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ ti,min-output-impedance; ++ }; ++}; ++ ++&mcasp1 { ++ status = "okay"; ++ #sound-dai-cells = <0>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_mcasp1_pins_default>; ++ ++ op-mode = <0>; /* MCASP_IIS_MODE */ ++ tdm-slots = <2>; ++ ++ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ ++ 1 0 2 0 ++ 0 0 0 0 ++ 0 0 0 0 ++ 0 0 0 0 ++ >; ++ tx-num-evt = <32>; ++ rx-num-evt = <32>; ++}; ++ ++&fss { ++ bootph-all; ++}; ++ ++&ospi0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ospi0_pins_default>; ++ bootph-all; ++ ++ flash@0{ ++ compatible = "jedec,spi-nor"; ++ reg = <0x0>; ++ spi-tx-bus-width = <8>; ++ spi-rx-bus-width = <8>; ++ spi-max-frequency = <25000000>; ++ cdns,tshsl-ns = <60>; ++ cdns,tsd2d-ns = <60>; ++ cdns,tchsh-ns = <60>; ++ cdns,tslch-ns = <60>; ++ cdns,read-delay = <4>; ++ bootph-all; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ bootph-all; ++ ++ partition@0 { ++ label = "ospi.tiboot3"; ++ reg = <0x00 0x80000>; ++ }; ++ ++ partition@80000 { ++ label = "ospi.tispl"; ++ reg = <0x80000 0x200000>; ++ }; ++ ++ partition@280000 { ++ label = "ospi.u-boot"; ++ reg = <0x280000 0x400000>; ++ }; ++ ++ partition@680000 { ++ label = "ospi.env"; ++ reg = <0x680000 0x40000>; ++ }; ++ ++ partition@6c0000 { ++ label = "ospi.env.backup"; ++ reg = <0x6c0000 0x40000>; ++ }; ++ ++ partition@800000 { ++ label = "ospi.rootfs"; ++ reg = <0x800000 0x37c0000>; ++ }; ++ ++ partition@3fc0000 { ++ label = "ospi.phypattern"; ++ reg = <0x3fc0000 0x40000>; ++ bootph-all; ++ }; ++ }; ++ }; ++}; ++ ++&mailbox0_cluster0 { ++ mbox_r5_0: mbox-r5-0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster1 { ++ mbox_mcu_r5_0: mbox-mcu-r5-0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++}; ++ ++&main_uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; + status = "okay"; ++ bootph-all; + }; + + &main_uart1 { +@@ -88,29 +577,36 @@ + pinctrl-0 = <&main_uart1_pins_default>; + /* Main UART1 is used by TIFS firmware */ + status = "reserved"; +-}; +- +-&cbass_mcu { + bootph-all; + }; + + &mcu_pmx0 { + bootph-all; ++ + wkup_uart0_pins_default: wkup-uart0-default-pins { +- bootph-all; + pinctrl-single,pins = < + AM62PX_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C7) WKUP_UART0_CTSn */ + AM62PX_MCU_IOPAD(0x030, PIN_OUTPUT, 0) /* (C6) WKUP_UART0_RTSn */ + AM62PX_MCU_IOPAD(0x024, PIN_INPUT, 0) /* (D8) WKUP_UART0_RXD */ + AM62PX_MCU_IOPAD(0x028, PIN_OUTPUT, 0) /* (D7) WKUP_UART0_TXD */ + >; ++ bootph-all; + }; + }; + + &wkup_uart0 { + /* WKUP UART0 is used by DM firmware */ +- bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; + status = "reserved"; ++ bootph-all; ++}; ++ ++/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */ ++&mcu_gpio0 { ++ status = "reserved"; ++}; ++ ++&mcu_gpio_intr { ++ status = "reserved"; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p.dtsi b/arch/arm64/boot/dts/ti/k3-am62p.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62p.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62p.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for AM62P SoC Family + * +- * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +@@ -45,10 +45,10 @@ + }; + + cbass_main: bus@f0000 { +- bootph-all; + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; ++ bootph-all; + + ranges = <0x00 0x000f0000 0x00 0x000f0000 0x00 0x00030000>, /* Main MMRs */ + <0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */ +@@ -71,7 +71,7 @@ + <0x00 0x43600000 0x00 0x43600000 0x00 0x00010000>, /* SA3 sproxy data */ + <0x00 0x44043000 0x00 0x44043000 0x00 0x00000fe0>, /* TI SCI DEBUG */ + <0x00 0x44860000 0x00 0x44860000 0x00 0x00040000>, /* SA3 sproxy config */ +- <0x00 0x48000000 0x00 0x48000000 0x00 0x06400000>, /* DMSS */ ++ <0x00 0x48000000 0x00 0x48000000 0x00 0x06408000>, /* DMSS */ + <0x00 0x60000000 0x00 0x60000000 0x00 0x08000000>, /* FSS0 DAT1 */ + <0x00 0x70000000 0x00 0x70000000 0x00 0x00010000>, /* OCSRAM */ + <0x01 0x00000000 0x01 0x00000000 0x00 0x00310000>, /* A53 PERIPHBASE */ +@@ -100,10 +100,10 @@ + <0x00 0x79020000 0x00 0x79020000 0x00 0x00008000>, /* MCU R5 BTCM */ + <0x00 0x79100000 0x00 0x79100000 0x00 0x00040000>, /* MCU IRAM0 */ + <0x00 0x79140000 0x00 0x79140000 0x00 0x00040000>; /* MCU IRAM1 */ ++ bootph-all; + }; + + cbass_wakeup: bus@b00000 { +- bootph-all; + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; +@@ -112,8 +112,11 @@ + <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>, /* WKUP CTRL MMR */ + <0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>, /* DM R5 ATCM*/ + <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; /* DM R5 BTCM*/ ++ bootph-all; + }; + }; ++ ++ #include "k3-am62p-thermal.dtsi" + }; + + /* Now include peripherals for each bus segment */ +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-phycore-som.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -317,7 +317,6 @@ + &sdhci0 { + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc0_pins_default>; +- ti,driver-strength-ohm = <50>; + disable-wp; + non-removable; + status = "okay"; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,7 +1,7 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree file for the AM62P main domain peripherals +- * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + &cbass_main { +@@ -40,18 +40,37 @@ + }; + }; + ++ main_conf: bus@100000 { ++ compatible = "simple-bus"; ++ reg = <0x00 0x00100000 0x00 0x20000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x00 0x00 0x00100000 0x20000>; ++ ++ phy_gmii_sel: phy@4044 { ++ compatible = "ti,am654-phy-gmii-sel"; ++ reg = <0x4044 0x8>; ++ #phy-cells = <1>; ++ }; ++ ++ epwm_tbclk: clock-controller@4130 { ++ compatible = "ti,am62-epwm-tbclk"; ++ reg = <0x4130 0x4>; ++ #clock-cells = <1>; ++ }; ++ }; ++ + dmss: bus@48000000 { +- bootph-all; +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + dma-ranges; + ranges = <0x00 0x48000000 0x00 0x48000000 0x00 0x06400000>; ++ bootph-all; + + ti,sci-dev-id = <25>; + + secure_proxy_main: mailbox@4d000000 { +- bootph-all; + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; +@@ -60,11 +79,123 @@ + <0x00 0x4a400000 0x00 0x80000>; + interrupt-names = "rx_012"; + interrupts = ; ++ bootph-all; ++ }; ++ ++ inta_main_dmss: interrupt-controller@48000000 { ++ compatible = "ti,sci-inta"; ++ reg = <0x00 0x48000000 0x00 0x100000>; ++ #interrupt-cells = <0>; ++ interrupt-controller; ++ interrupt-parent = <&gic500>; ++ msi-controller; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <28>; ++ ti,interrupt-ranges = <5 69 35>; ++ ti,unmapped-event-sources = <&main_bcdma>, <&main_pktdma>; ++ }; ++ ++ main_bcdma: dma-controller@485c0100 { ++ compatible = "ti,am64-dmss-bcdma"; ++ reg = <0x00 0x485c0100 0x00 0x100>, ++ <0x00 0x4c000000 0x00 0x20000>, ++ <0x00 0x4a820000 0x00 0x20000>, ++ <0x00 0x4aa40000 0x00 0x20000>, ++ <0x00 0x4bc00000 0x00 0x100000>, ++ <0x00 0x48600000 0x00 0x8000>, ++ <0x00 0x484a4000 0x00 0x2000>, ++ <0x00 0x484c2000 0x00 0x2000>, ++ <0x00 0x48420000 0x00 0x2000>; ++ reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "bchan"; ++ msi-parent = <&inta_main_dmss>; ++ #dma-cells = <3>; ++ ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <26>; ++ ti,sci-rm-range-bchan = <0x20>; /* BLOCK_COPY_CHAN */ ++ ti,sci-rm-range-rchan = <0x21>; /* SPLIT_TR_RX_CHAN */ ++ ti,sci-rm-range-tchan = <0x22>; /* SPLIT_TR_TX_CHAN */ ++ bootph-all; ++ }; ++ ++ main_pktdma: dma-controller@485c0000 { ++ compatible = "ti,am64-dmss-pktdma"; ++ reg = <0x00 0x485c0000 0x00 0x100>, ++ <0x00 0x4a800000 0x00 0x20000>, ++ <0x00 0x4aa00000 0x00 0x40000>, ++ <0x00 0x4b800000 0x00 0x400000>, ++ <0x00 0x485e0000 0x00 0x10000>, ++ <0x00 0x484a0000 0x00 0x2000>, ++ <0x00 0x484c0000 0x00 0x2000>, ++ <0x00 0x48430000 0x00 0x1000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "rflow"; ++ msi-parent = <&inta_main_dmss>; ++ #dma-cells = <2>; ++ bootph-all; ++ ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <30>; ++ ti,sci-rm-range-tchan = <0x23>, /* UNMAPPED_TX_CHAN */ ++ <0x24>, /* CPSW_TX_CHAN */ ++ <0x25>, /* SAUL_TX_0_CHAN */ ++ <0x26>; /* SAUL_TX_1_CHAN */ ++ ti,sci-rm-range-tflow = <0x10>, /* RING_UNMAPPED_TX_CHAN */ ++ <0x11>, /* RING_CPSW_TX_CHAN */ ++ <0x12>, /* RING_SAUL_TX_0_CHAN */ ++ <0x13>; /* RING_SAUL_TX_1_CHAN */ ++ ti,sci-rm-range-rchan = <0x29>, /* UNMAPPED_RX_CHAN */ ++ <0x2b>, /* CPSW_RX_CHAN */ ++ <0x2d>, /* SAUL_RX_0_CHAN */ ++ <0x2f>, /* SAUL_RX_1_CHAN */ ++ <0x31>, /* SAUL_RX_2_CHAN */ ++ <0x33>; /* SAUL_RX_3_CHAN */ ++ ti,sci-rm-range-rflow = <0x2a>, /* FLOW_UNMAPPED_RX_CHAN */ ++ <0x2c>, /* FLOW_CPSW_RX_CHAN */ ++ <0x2e>, /* FLOW_SAUL_RX_0/1_CHAN */ ++ <0x32>; /* FLOW_SAUL_RX_2/3_CHAN */ ++ }; ++ }; ++ ++ dmss_csi: bus@4e000000 { ++ compatible = "simple-bus"; ++ ranges = <0x00 0x4e000000 0x00 0x4e000000 0x00 0x408000>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dma-ranges; ++ ti,sci-dev-id = <198>; ++ ++ inta_main_dmss_csi: interrupt-controller@4e400000 { ++ compatible = "ti,sci-inta"; ++ reg = <0x00 0x4e400000 0x00 0x8000>; ++ #interrupt-cells = <0>; ++ interrupt-controller; ++ interrupt-parent = <&gic500>; ++ msi-controller; ++ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <200>; ++ ti,interrupt-ranges = <0 237 8>; ++ ti,unmapped-event-sources = <&main_bcdma_csi>; ++ }; ++ ++ main_bcdma_csi: dma-controller@4e230000 { ++ compatible = "ti,am62a-dmss-bcdma-csirx"; ++ reg = <0x00 0x4e230000 0x00 0x100>, ++ <0x00 0x4e180000 0x00 0x8000>, ++ <0x00 0x4e100000 0x00 0x10000>; ++ reg-names = "gcfg", "rchanrt", "ringrt"; ++ #dma-cells = <3>; ++ msi-parent = <&inta_main_dmss_csi>; ++ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <199>; ++ ti,sci-rm-range-rchan = <0x21>; + }; + }; + + dmsc: system-controller@44043000 { +- bootph-all; + compatible = "ti,k2g-sci"; + ti,host-id = <12>; + mbox-names = "rx", "tx"; +@@ -72,37 +203,72 @@ + <&secure_proxy_main 13>; + reg-names = "debug_messages"; + reg = <0x00 0x44043000 0x00 0xfe0>; ++ bootph-all; + + k3_pds: power-controller { +- bootph-all; + compatible = "ti,sci-pm-domain"; + #power-domain-cells = <2>; ++ bootph-all; + }; + + k3_clks: clock-controller { +- bootph-all; + compatible = "ti,k2g-sci-clk"; + #clock-cells = <2>; ++ bootph-all; + }; + + k3_reset: reset-controller { +- bootph-all; + compatible = "ti,sci-reset"; + #reset-cells = <2>; ++ bootph-all; + }; + }; + +- main_pmx0: pinctrl@f4000 { ++ crypto: crypto@40900000 { ++ compatible = "ti,am62-sa3ul"; ++ reg = <0x00 0x40900000 0x00 0x1200>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges = <0x00 0x40900000 0x00 0x40900000 0x00 0x30000>; ++ ++ dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>, ++ <&main_pktdma 0x7507 0>; ++ dma-names = "tx", "rx1", "rx2"; ++ }; ++ ++ secure_proxy_sa3: mailbox@43600000 { ++ compatible = "ti,am654-secure-proxy"; ++ #mbox-cells = <1>; ++ reg-names = "target_data", "rt", "scfg"; ++ reg = <0x00 0x43600000 0x00 0x10000>, ++ <0x00 0x44880000 0x00 0x20000>, ++ <0x00 0x44860000 0x00 0x20000>; ++ /* ++ * Marked Disabled: ++ * Node is incomplete as it is meant for bootloaders and ++ * firmware on non-MPU processors ++ */ ++ status = "disabled"; + bootph-all; ++ }; ++ ++ main_pmx0: pinctrl@f4000 { + compatible = "pinctrl-single"; + reg = <0x00 0xf4000 0x00 0x2ac>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; ++ bootph-all; ++ }; ++ ++ main_esm: esm@420000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x420000 0x00 0x1000>; ++ ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>; ++ bootph-pre-ram; + }; + + main_timer0: timer@2400000 { +- bootph-all; + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; +@@ -112,6 +278,91 @@ + assigned-clock-parents = <&k3_clks 36 3>; + power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>; + ti,timer-pwm; ++ bootph-all; ++ }; ++ ++ main_timer1: timer@2410000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x2410000 0x00 0x400>; ++ interrupts = ; ++ clocks = <&k3_clks 37 2>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 37 2>; ++ assigned-clock-parents = <&k3_clks 37 3>; ++ power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ }; ++ ++ main_timer2: timer@2420000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x2420000 0x00 0x400>; ++ interrupts = ; ++ clocks = <&k3_clks 38 2>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 38 2>; ++ assigned-clock-parents = <&k3_clks 38 3>; ++ power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ }; ++ ++ main_timer3: timer@2430000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x2430000 0x00 0x400>; ++ interrupts = ; ++ clocks = <&k3_clks 39 2>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 39 2>; ++ assigned-clock-parents = <&k3_clks 39 3>; ++ power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ }; ++ ++ main_timer4: timer@2440000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x2440000 0x00 0x400>; ++ interrupts = ; ++ clocks = <&k3_clks 40 2>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 40 2>; ++ assigned-clock-parents = <&k3_clks 40 3>; ++ power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ }; ++ ++ main_timer5: timer@2450000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x2450000 0x00 0x400>; ++ interrupts = ; ++ clocks = <&k3_clks 41 2>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 41 2>; ++ assigned-clock-parents = <&k3_clks 41 3>; ++ power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ }; ++ ++ main_timer6: timer@2460000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x2460000 0x00 0x400>; ++ interrupts = ; ++ clocks = <&k3_clks 42 2>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 42 2>; ++ assigned-clock-parents = <&k3_clks 42 3>; ++ power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ }; ++ ++ main_timer7: timer@2470000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x2470000 0x00 0x400>; ++ interrupts = ; ++ clocks = <&k3_clks 43 2>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 43 2>; ++ assigned-clock-parents = <&k3_clks 43 3>; ++ power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; + }; + + main_uart0: serial@2800000 { +@@ -133,4 +384,655 @@ + clock-names = "fclk"; + status = "disabled"; + }; ++ ++ main_uart2: serial@2820000 { ++ compatible = "ti,am64-uart", "ti,am654-uart"; ++ reg = <0x00 0x02820000 0x00 0x100>; ++ interrupts = ; ++ power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 153 0>; ++ clock-names = "fclk"; ++ status = "disabled"; ++ }; ++ ++ main_uart3: serial@2830000 { ++ compatible = "ti,am64-uart", "ti,am654-uart"; ++ reg = <0x00 0x02830000 0x00 0x100>; ++ interrupts = ; ++ power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 154 0>; ++ clock-names = "fclk"; ++ status = "disabled"; ++ }; ++ ++ main_uart4: serial@2840000 { ++ compatible = "ti,am64-uart", "ti,am654-uart"; ++ reg = <0x00 0x02840000 0x00 0x100>; ++ interrupts = ; ++ power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 155 0>; ++ clock-names = "fclk"; ++ status = "disabled"; ++ }; ++ ++ main_uart5: serial@2850000 { ++ compatible = "ti,am64-uart", "ti,am654-uart"; ++ reg = <0x00 0x02850000 0x00 0x100>; ++ interrupts = ; ++ power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 156 0>; ++ clock-names = "fclk"; ++ status = "disabled"; ++ }; ++ ++ main_uart6: serial@2860000 { ++ compatible = "ti,am64-uart", "ti,am654-uart"; ++ reg = <0x00 0x02860000 0x00 0x100>; ++ interrupts = ; ++ power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 158 0>; ++ clock-names = "fclk"; ++ status = "disabled"; ++ }; ++ ++ main_i2c0: i2c@20000000 { ++ compatible = "ti,am64-i2c", "ti,omap4-i2c"; ++ reg = <0x00 0x20000000 0x00 0x100>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 102 2>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ main_i2c1: i2c@20010000 { ++ compatible = "ti,am64-i2c", "ti,omap4-i2c"; ++ reg = <0x00 0x20010000 0x00 0x100>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 103 2>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ main_i2c2: i2c@20020000 { ++ compatible = "ti,am64-i2c", "ti,omap4-i2c"; ++ reg = <0x00 0x20020000 0x00 0x100>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 104 2>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ main_i2c3: i2c@20030000 { ++ compatible = "ti,am64-i2c", "ti,omap4-i2c"; ++ reg = <0x00 0x20030000 0x00 0x100>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 105 2>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ main_spi0: spi@20100000 { ++ compatible = "ti,am654-mcspi", "ti,omap4-mcspi"; ++ reg = <0x00 0x20100000 0x00 0x400>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 141 0>; ++ status = "disabled"; ++ }; ++ ++ main_spi1: spi@20110000 { ++ compatible = "ti,am654-mcspi","ti,omap4-mcspi"; ++ reg = <0x00 0x20110000 0x00 0x400>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 142 0>; ++ status = "disabled"; ++ }; ++ ++ main_spi2: spi@20120000 { ++ compatible = "ti,am654-mcspi","ti,omap4-mcspi"; ++ reg = <0x00 0x20120000 0x00 0x400>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 143 0>; ++ status = "disabled"; ++ }; ++ ++ main_gpio_intr: interrupt-controller@a00000 { ++ compatible = "ti,sci-intr"; ++ reg = <0x00 0x00a00000 0x00 0x800>; ++ ti,intr-trigger-type = <1>; ++ interrupt-controller; ++ interrupt-parent = <&gic500>; ++ #interrupt-cells = <1>; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <3>; ++ ti,interrupt-ranges = <0 32 16>; ++ }; ++ ++ main_gpio0: gpio@600000 { ++ compatible = "ti,am64-gpio", "ti,keystone-gpio"; ++ reg = <0x00 0x00600000 0x00 0x100>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-parent = <&main_gpio_intr>; ++ interrupts = <190>, <191>, <192>, ++ <193>, <194>, <195>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,ngpio = <92>; ++ ti,davinci-gpio-unbanked = <0>; ++ power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 77 0>; ++ clock-names = "gpio"; ++ }; ++ ++ main_gpio1: gpio@601000 { ++ compatible = "ti,am64-gpio", "ti,keystone-gpio"; ++ reg = <0x00 0x00601000 0x00 0x100>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-parent = <&main_gpio_intr>; ++ interrupts = <180>, <181>, <182>, ++ <183>, <184>, <185>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,ngpio = <52>; ++ ti,davinci-gpio-unbanked = <0>; ++ power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 78 0>; ++ clock-names = "gpio"; ++ }; ++ ++ sdhci0: mmc@fa10000 { ++ compatible = "ti,am64-sdhci-8bit"; ++ reg = <0x00 0x0fa10000 0x00 0x1000>, <0x00 0x0fa18000 0x00 0x400>; ++ interrupts = ; ++ power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 57 1>, <&k3_clks 57 2>; ++ clock-names = "clk_ahb", "clk_xin"; ++ assigned-clocks = <&k3_clks 57 2>; ++ assigned-clock-parents = <&k3_clks 57 4>; ++ bus-width = <8>; ++ mmc-ddr-1_8v; ++ mmc-hs200-1_8v; ++ mmc-hs400-1_8v; ++ ti,clkbuf-sel = <0x7>; ++ ti,strobe-sel = <0x77>; ++ ti,trm-icp = <0x8>; ++ ti,otap-del-sel-legacy = <0x1>; ++ ti,otap-del-sel-mmc-hs = <0x1>; ++ ti,otap-del-sel-ddr52 = <0x6>; ++ ti,otap-del-sel-hs200 = <0x8>; ++ ti,otap-del-sel-hs400 = <0x5>; ++ ti,itap-del-sel-legacy = <0x10>; ++ ti,itap-del-sel-mmc-hs = <0xa>; ++ ti,itap-del-sel-ddr52 = <0x3>; ++ status = "disabled"; ++ }; ++ ++ sdhci1: mmc@fa00000 { ++ compatible = "ti,am62-sdhci"; ++ reg = <0x00 0x0fa00000 0x00 0x1000>, <0x00 0x0fa08000 0x00 0x400>; ++ interrupts = ; ++ power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 58 5>, <&k3_clks 58 6>; ++ clock-names = "clk_ahb", "clk_xin"; ++ bus-width = <4>; ++ ti,clkbuf-sel = <0x7>; ++ ti,otap-del-sel-legacy = <0x0>; ++ ti,otap-del-sel-sd-hs = <0x0>; ++ ti,otap-del-sel-sdr12 = <0xf>; ++ ti,otap-del-sel-sdr25 = <0xf>; ++ ti,otap-del-sel-sdr50 = <0xc>; ++ ti,otap-del-sel-ddr50 = <0x9>; ++ ti,otap-del-sel-sdr104 = <0x6>; ++ ti,itap-del-sel-legacy = <0x0>; ++ ti,itap-del-sel-sd-hs = <0x0>; ++ ti,itap-del-sel-sdr12 = <0x0>; ++ ti,itap-del-sel-sdr25 = <0x0>; ++ status = "disabled"; ++ }; ++ ++ sdhci2: mmc@fa20000 { ++ compatible = "ti,am62-sdhci"; ++ reg = <0x00 0x0fa20000 0x00 0x1000>, <0x00 0x0fa28000 0x00 0x400>; ++ interrupts = ; ++ power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 184 5>, <&k3_clks 184 6>; ++ clock-names = "clk_ahb", "clk_xin"; ++ bus-width = <4>; ++ ti,clkbuf-sel = <0x7>; ++ ti,otap-del-sel-legacy = <0x0>; ++ ti,otap-del-sel-sd-hs = <0x0>; ++ ti,otap-del-sel-sdr12 = <0xf>; ++ ti,otap-del-sel-sdr25 = <0xf>; ++ ti,otap-del-sel-sdr50 = <0xc>; ++ ti,otap-del-sel-ddr50 = <0x9>; ++ ti,otap-del-sel-sdr104 = <0x6>; ++ ti,itap-del-sel-legacy = <0x0>; ++ ti,itap-del-sel-sd-hs = <0x0>; ++ ti,itap-del-sel-sdr12 = <0x0>; ++ ti,itap-del-sel-sdr25 = <0x0>; ++ status = "disabled"; ++ }; ++ ++ fss: bus@fc00000 { ++ compatible = "simple-bus"; ++ reg = <0x00 0x0fc00000 0x00 0x70000>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ ospi0: spi@fc40000 { ++ compatible = "ti,am654-ospi", "cdns,qspi-nor"; ++ reg = <0x00 0x0fc40000 0x00 0x100>, ++ <0x05 0x00000000 0x01 0x00000000>; ++ interrupts = ; ++ cdns,fifo-depth = <256>; ++ cdns,fifo-width = <4>; ++ cdns,trigger-address = <0x0>; ++ clocks = <&k3_clks 75 7>; ++ assigned-clocks = <&k3_clks 75 7>; ++ assigned-clock-parents = <&k3_clks 75 8>; ++ assigned-clock-rates = <166666666>; ++ power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ ++ cpsw3g: ethernet@8000000 { ++ compatible = "ti,am642-cpsw-nuss"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ reg = <0x00 0x08000000 0x00 0x200000>; ++ reg-names = "cpsw_nuss"; ++ ranges = <0x00 0x00 0x00 0x08000000 0x00 0x200000>; ++ clocks = <&k3_clks 13 0>; ++ assigned-clocks = <&k3_clks 13 3>; ++ assigned-clock-parents = <&k3_clks 13 11>; ++ clock-names = "fck"; ++ power-domains = <&k3_pds 13 TI_SCI_PD_EXCLUSIVE>; ++ ++ dmas = <&main_pktdma 0xc600 15>, ++ <&main_pktdma 0xc601 15>, ++ <&main_pktdma 0xc602 15>, ++ <&main_pktdma 0xc603 15>, ++ <&main_pktdma 0xc604 15>, ++ <&main_pktdma 0xc605 15>, ++ <&main_pktdma 0xc606 15>, ++ <&main_pktdma 0xc607 15>, ++ <&main_pktdma 0x4600 15>; ++ dma-names = "tx0", "tx1", "tx2", "tx3", "tx4", "tx5", "tx6", ++ "tx7", "rx"; ++ ++ ethernet-ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ cpsw_port1: port@1 { ++ reg = <1>; ++ ti,mac-only; ++ label = "port1"; ++ phys = <&phy_gmii_sel 1>; ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ cpsw_port2: port@2 { ++ reg = <2>; ++ ti,mac-only; ++ label = "port2"; ++ phys = <&phy_gmii_sel 2>; ++ mac-address = [00 00 00 00 00 00]; ++ }; ++ }; ++ ++ cpsw3g_mdio: mdio@f00 { ++ compatible = "ti,cpsw-mdio","ti,davinci_mdio"; ++ reg = <0x00 0xf00 0x00 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clocks = <&k3_clks 13 0>; ++ clock-names = "fck"; ++ bus_freq = <1000000>; ++ status = "disabled"; ++ }; ++ ++ cpts@3d000 { ++ compatible = "ti,j721e-cpts"; ++ reg = <0x00 0x3d000 0x00 0x400>; ++ clocks = <&k3_clks 13 3>; ++ clock-names = "cpts"; ++ interrupts-extended = <&gic500 GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-names = "cpts"; ++ ti,cpts-ext-ts-inputs = <4>; ++ ti,cpts-periodic-outputs = <2>; ++ }; ++ }; ++ ++ hwspinlock: spinlock@2a000000 { ++ compatible = "ti,am64-hwspinlock"; ++ reg = <0x00 0x2a000000 0x00 0x1000>; ++ #hwlock-cells = <1>; ++ }; ++ ++ mailbox0_cluster0: mailbox@29000000 { ++ compatible = "ti,am64-mailbox"; ++ reg = <0x00 0x29000000 0x00 0x200>; ++ interrupts = ; ++ #mbox-cells = <1>; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <16>; ++ }; ++ ++ mailbox0_cluster1: mailbox@29010000 { ++ compatible = "ti,am64-mailbox"; ++ reg = <0x00 0x29010000 0x00 0x200>; ++ interrupts = ; ++ #mbox-cells = <1>; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <16>; ++ }; ++ ++ mailbox0_cluster2: mailbox@29020000 { ++ compatible = "ti,am64-mailbox"; ++ reg = <0x00 0x29020000 0x00 0x200>; ++ interrupts = ; ++ #mbox-cells = <1>; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <16>; ++ }; ++ ++ mailbox0_cluster3: mailbox@29030000 { ++ compatible = "ti,am64-mailbox"; ++ reg = <0x00 0x29030000 0x00 0x200>; ++ interrupts = ; ++ #mbox-cells = <1>; ++ ti,mbox-num-users = <4>; ++ ti,mbox-num-fifos = <16>; ++ }; ++ ++ ecap0: pwm@23100000 { ++ compatible = "ti,am3352-ecap"; ++ #pwm-cells = <3>; ++ reg = <0x00 0x23100000 0x00 0x100>; ++ power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 51 0>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ ecap1: pwm@23110000 { ++ compatible = "ti,am3352-ecap"; ++ #pwm-cells = <3>; ++ reg = <0x00 0x23110000 0x00 0x100>; ++ power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 52 0>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ ecap2: pwm@23120000 { ++ compatible = "ti,am3352-ecap"; ++ #pwm-cells = <3>; ++ reg = <0x00 0x23120000 0x00 0x100>; ++ power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 53 0>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ main_mcan0: can@20701000 { ++ compatible = "bosch,m_can"; ++ reg = <0x00 0x20701000 0x00 0x200>, ++ <0x00 0x20708000 0x00 0x8000>; ++ reg-names = "m_can", "message_ram"; ++ power-domains = <&k3_pds 98 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 98 6>, <&k3_clks 98 1>; ++ clock-names = "hclk", "cclk"; ++ interrupts = , ++ ; ++ interrupt-names = "int0", "int1"; ++ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; ++ status = "disabled"; ++ }; ++ ++ main_mcan1: can@20711000 { ++ compatible = "bosch,m_can"; ++ reg = <0x00 0x20711000 0x00 0x200>, ++ <0x00 0x20718000 0x00 0x8000>; ++ reg-names = "m_can", "message_ram"; ++ power-domains = <&k3_pds 99 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 99 6>, <&k3_clks 99 1>; ++ clock-names = "hclk", "cclk"; ++ interrupts = , ++ ; ++ interrupt-names = "int0", "int1"; ++ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; ++ status = "disabled"; ++ }; ++ ++ main_rti0: watchdog@e000000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x0e000000 0x00 0x100>; ++ clocks = <&k3_clks 125 0>; ++ power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 125 0>; ++ assigned-clock-parents = <&k3_clks 125 2>; ++ }; ++ ++ main_rti1: watchdog@e010000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x0e010000 0x00 0x100>; ++ clocks = <&k3_clks 126 0>; ++ power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 126 0>; ++ assigned-clock-parents = <&k3_clks 126 2>; ++ }; ++ ++ main_rti2: watchdog@e020000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x0e020000 0x00 0x100>; ++ clocks = <&k3_clks 127 0>; ++ power-domains = <&k3_pds 127 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 127 0>; ++ assigned-clock-parents = <&k3_clks 127 2>; ++ }; ++ ++ main_rti3: watchdog@e030000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x0e030000 0x00 0x100>; ++ clocks = <&k3_clks 128 0>; ++ power-domains = <&k3_pds 128 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 128 0>; ++ assigned-clock-parents = <&k3_clks 128 2>; ++ }; ++ ++ main_rti15: watchdog@e0f0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x0e0f0000 0x00 0x100>; ++ clocks = <&k3_clks 130 0>; ++ power-domains = <&k3_pds 130 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 130 0>; ++ assigned-clock-parents = <&k3_clks 130 2>; ++ }; ++ ++ epwm0: pwm@23000000 { ++ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm"; ++ #pwm-cells = <3>; ++ reg = <0x00 0x23000000 0x00 0x100>; ++ power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>; ++ clock-names = "tbclk", "fck"; ++ status = "disabled"; ++ }; ++ ++ epwm1: pwm@23010000 { ++ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm"; ++ #pwm-cells = <3>; ++ reg = <0x00 0x23010000 0x00 0x100>; ++ power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>; ++ clock-names = "tbclk", "fck"; ++ status = "disabled"; ++ }; ++ ++ epwm2: pwm@23020000 { ++ compatible = "ti,am64-epwm", "ti,am3352-ehrpwm"; ++ #pwm-cells = <3>; ++ reg = <0x00 0x23020000 0x00 0x100>; ++ power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>; ++ clock-names = "tbclk", "fck"; ++ status = "disabled"; ++ }; ++ ++ mcasp0: audio-controller@2b00000 { ++ compatible = "ti,am33xx-mcasp-audio"; ++ reg = <0x00 0x02b00000 0x00 0x2000>, ++ <0x00 0x02b08000 0x00 0x400>; ++ reg-names = "mpu", "dat"; ++ interrupts = , ++ ; ++ interrupt-names = "tx", "rx"; ++ ++ dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>; ++ dma-names = "tx", "rx"; ++ ++ clocks = <&k3_clks 190 0>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 190 0>; ++ assigned-clock-parents = <&k3_clks 190 2>; ++ power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ mcasp1: audio-controller@2b10000 { ++ compatible = "ti,am33xx-mcasp-audio"; ++ reg = <0x00 0x02b10000 0x00 0x2000>, ++ <0x00 0x02b18000 0x00 0x400>; ++ reg-names = "mpu", "dat"; ++ interrupts = , ++ ; ++ interrupt-names = "tx", "rx"; ++ ++ dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>; ++ dma-names = "tx", "rx"; ++ ++ clocks = <&k3_clks 191 0>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 191 0>; ++ assigned-clock-parents = <&k3_clks 191 2>; ++ power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ mcasp2: audio-controller@2b20000 { ++ compatible = "ti,am33xx-mcasp-audio"; ++ reg = <0x00 0x02b20000 0x00 0x2000>, ++ <0x00 0x02b28000 0x00 0x400>; ++ reg-names = "mpu", "dat"; ++ interrupts = , ++ ; ++ interrupt-names = "tx", "rx"; ++ ++ dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>; ++ dma-names = "tx", "rx"; ++ ++ clocks = <&k3_clks 192 0>; ++ clock-names = "fck"; ++ assigned-clocks = <&k3_clks 192 0>; ++ assigned-clock-parents = <&k3_clks 192 2>; ++ power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ ti_csi2rx0: ticsi2rx@30102000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ reg = <0x00 0x30102000 0x00 0x1000>; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dmas = <&main_bcdma_csi 0 0x5000 0>; ++ dma-names = "rx0"; ++ power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ cdns_csi2rx0: csi-bridge@30101000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x00 0x30101000 0x00 0x1000>; ++ clocks = <&k3_clks 182 0>, <&k3_clks 182 3>, <&k3_clks 182 0>, ++ <&k3_clks 182 0>, <&k3_clks 182 4>, <&k3_clks 182 4>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy0>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi0_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi0_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi0_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi0_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ dphy0: phy@30110000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x00 0x30110000 0x00 0x1100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ vpu: video-codec@30210000 { ++ compatible = "ti,j721s2-wave521c", "cnm,wave521c"; ++ reg = <0x00 0x30210000 0x00 0x10000>; ++ interrupts = ; ++ clocks = <&k3_clks 204 2>; ++ power-domains = <&k3_pds 204 TI_SCI_PD_EXCLUSIVE>; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,7 +1,7 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree file for the AM62P MCU domain peripherals +- * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + &cbass_mcu { +@@ -11,5 +11,197 @@ + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; ++ bootph-all; ++ }; ++ ++ mcu_esm: esm@4100000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x4100000 0x00 0x1000>; ++ ti,esm-pins = <0>, <1>, <2>, <85>; ++ status = "reserved"; ++ bootph-pre-ram; ++ }; ++ ++ /* ++ * The MCU domain timer interrupts are routed only to the ESM module, ++ * and not currently available for Linux. The MCU domain timers are ++ * of limited use without interrupts, and likely reserved by the ESM. ++ */ ++ mcu_timer0: timer@4800000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x4800000 0x00 0x400>; ++ clocks = <&k3_clks 35 2>; ++ clock-names = "fck"; ++ power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ status = "reserved"; ++ }; ++ ++ mcu_timer1: timer@4810000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x4810000 0x00 0x400>; ++ clocks = <&k3_clks 48 2>; ++ clock-names = "fck"; ++ power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ status = "reserved"; ++ }; ++ ++ mcu_timer2: timer@4820000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x4820000 0x00 0x400>; ++ clocks = <&k3_clks 49 2>; ++ clock-names = "fck"; ++ power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ status = "reserved"; ++ }; ++ ++ mcu_timer3: timer@4830000 { ++ compatible = "ti,am654-timer"; ++ reg = <0x00 0x4830000 0x00 0x400>; ++ clocks = <&k3_clks 50 2>; ++ clock-names = "fck"; ++ power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>; ++ ti,timer-pwm; ++ status = "reserved"; ++ }; ++ ++ mcu_uart0: serial@4a00000 { ++ compatible = "ti,am64-uart", "ti,am654-uart"; ++ reg = <0x00 0x04a00000 0x00 0x100>; ++ interrupts = ; ++ power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 149 0>; ++ clock-names = "fclk"; ++ status = "disabled"; ++ }; ++ ++ mcu_i2c0: i2c@4900000 { ++ compatible = "ti,am64-i2c", "ti,omap4-i2c"; ++ reg = <0x00 0x04900000 0x00 0x100>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 106 2>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ mcu_spi0: spi@4b00000 { ++ compatible = "ti,am654-mcspi", "ti,omap4-mcspi"; ++ reg = <0x00 0x04b00000 0x00 0x400>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 147 0>; ++ status = "disabled"; ++ }; ++ ++ mcu_spi1: spi@4b10000 { ++ compatible = "ti,am654-mcspi","ti,omap4-mcspi"; ++ reg = <0x00 0x04b10000 0x00 0x400>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 148 0>; ++ status = "disabled"; ++ }; ++ ++ mcu_gpio_intr: interrupt-controller@4210000 { ++ compatible = "ti,sci-intr"; ++ reg = <0x00 0x04210000 0x00 0x200>; ++ ti,intr-trigger-type = <1>; ++ interrupt-controller; ++ interrupt-parent = <&gic500>; ++ #interrupt-cells = <1>; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <5>; ++ ti,interrupt-ranges = <0 104 4>; ++ }; ++ ++ mcu_gpio0: gpio@4201000 { ++ compatible = "ti,am64-gpio", "ti,keystone-gpio"; ++ reg = <0x00 0x4201000 0x00 0x100>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-parent = <&mcu_gpio_intr>; ++ interrupts = <30>, <31>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ ti,ngpio = <24>; ++ ti,davinci-gpio-unbanked = <0>; ++ power-domains = <&k3_pds 79 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 79 0>; ++ clock-names = "gpio"; ++ }; ++ ++ mcu_rti0: watchdog@4880000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x04880000 0x00 0x100>; ++ clocks = <&k3_clks 131 0>; ++ power-domains = <&k3_pds 131 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 131 0>; ++ assigned-clock-parents = <&k3_clks 131 2>; ++ /* Tightly coupled to M4F */ ++ status = "reserved"; ++ }; ++ ++ mcu_mcan0: can@4e08000 { ++ compatible = "bosch,m_can"; ++ reg = <0x00 0x4e08000 0x00 0x200>, ++ <0x00 0x4e00000 0x00 0x8000>; ++ reg-names = "m_can", "message_ram"; ++ power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 188 6>, <&k3_clks 188 1>; ++ clock-names = "hclk", "cclk"; ++ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; ++ interrupts = , ++ ; ++ interrupt-names = "int0", "int1"; ++ status = "disabled"; ++ }; ++ ++ mcu_mcan1: can@4e18000 { ++ compatible = "bosch,m_can"; ++ reg = <0x00 0x4e18000 0x00 0x200>, ++ <0x00 0x4e10000 0x00 0x8000>; ++ reg-names = "m_can", "message_ram"; ++ power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 189 6>, <&k3_clks 189 1>; ++ clock-names = "hclk", "cclk"; ++ bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; ++ interrupts = , ++ ; ++ interrupt-names = "int0", "int1"; ++ status = "disabled"; ++ }; ++ ++ mcu_r5fss0: r5fss@79000000 { ++ compatible = "ti,am62-r5fss"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x79000000 0x00 0x79000000 0x8000>, ++ <0x79020000 0x00 0x79020000 0x8000>; ++ power-domains = <&k3_pds 7 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ mcu_r5fss0_core0: r5f@79000000 { ++ compatible = "ti,am62-r5f"; ++ reg = <0x79000000 0x00008000>, ++ <0x79020000 0x00008000>; ++ reg-names = "atcm", "btcm"; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <9>; ++ ti,sci-proc-ids = <0x03 0xff>; ++ resets = <&k3_reset 9 1>; ++ firmware-name = "am62p-mcu-r5f0_0-fw"; ++ ti,atcm-enable = <0>; ++ ti,btcm-enable = <1>; ++ ti,loczrama = <0>; ++ }; + }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/* ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++#include ++ ++thermal_zones: thermal-zones { ++ main0_thermal: main0-thermal { ++ polling-delay-passive = <250>; /* milliSeconds */ ++ polling-delay = <500>; /* milliSeconds */ ++ thermal-sensors = <&wkup_vtm0 0>; ++ ++ trips { ++ main0_crit: main0-crit { ++ temperature = <125000>; /* milliCelsius */ ++ hysteresis = <2000>; /* milliCelsius */ ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ main1_thermal: main1-thermal { ++ polling-delay-passive = <250>; /* milliSeconds */ ++ polling-delay = <500>; /* milliSeconds */ ++ thermal-sensors = <&wkup_vtm0 1>; ++ ++ trips { ++ main1_crit: main1-crit { ++ temperature = <125000>; /* milliCelsius */ ++ hysteresis = <2000>; /* milliCelsius */ ++ type = "critical"; ++ }; ++ }; ++ }; ++ ++ main2_thermal: main2-thermal { ++ polling-delay-passive = <250>; /* milliSeconds */ ++ polling-delay = <500>; /* milliSeconds */ ++ thermal-sensors = <&wkup_vtm0 2>; ++ ++ trips { ++ main2_crit: main2-crit { ++ temperature = <125000>; /* milliCelsius */ ++ hysteresis = <2000>; /* milliCelsius */ ++ type = "critical"; ++ }; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,22 +1,22 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree file for the AM62P wakeup domain peripherals +- * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + &cbass_wakeup { + wkup_conf: bus@43000000 { +- bootph-all; + compatible = "simple-bus"; + reg = <0x00 0x43000000 0x00 0x20000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00 0x00 0x43000000 0x20000>; ++ bootph-all; + + chipid: chipid@14 { +- bootph-all; + compatible = "ti,am654-chipid"; + reg = <0x14 0x4>; ++ bootph-all; + }; + }; + +@@ -29,4 +29,70 @@ + clock-names = "fclk"; + status = "disabled"; + }; ++ ++ wkup_i2c0: i2c@2b200000 { ++ compatible = "ti,am64-i2c", "ti,omap4-i2c"; ++ reg = <0x00 0x2b200000 0x00 0x100>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 107 4>; ++ clock-names = "fck"; ++ status = "disabled"; ++ }; ++ ++ wkup_rtc0: rtc@2b1f0000 { ++ compatible = "ti,am62-rtc"; ++ reg = <0x00 0x2b1f0000 0x00 0x100>; ++ interrupts = ; ++ clocks = <&k3_clks 117 6> , <&k3_clks 117 0>; ++ clock-names = "vbus", "osc32k"; ++ power-domains = <&k3_pds 117 TI_SCI_PD_EXCLUSIVE>; ++ wakeup-source; ++ }; ++ ++ wkup_rti0: watchdog@2b000000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2b000000 0x00 0x100>; ++ clocks = <&k3_clks 132 0>; ++ power-domains = <&k3_pds 132 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 132 0>; ++ assigned-clock-parents = <&k3_clks 132 2>; ++ /* Used by DM firmware */ ++ status = "reserved"; ++ }; ++ ++ wkup_vtm0: temperature-sensor@b00000 { ++ compatible = "ti,j7200-vtm"; ++ reg = <0x00 0xb00000 0x00 0x400>, ++ <0x00 0xb01000 0x00 0x400>; ++ power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>; ++ #thermal-sensor-cells = <1>; ++ }; ++ ++ wkup_r5fss0: r5fss@78000000 { ++ compatible = "ti,am62-r5fss"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x78000000 0x00 0x78000000 0x8000>, ++ <0x78100000 0x00 0x78100000 0x8000>; ++ power-domains = <&k3_pds 119 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ wkup_r5fss0_core0: r5f@78000000 { ++ compatible = "ti,am62-r5f"; ++ reg = <0x78000000 0x00008000>, ++ <0x78100000 0x00008000>; ++ reg-names = "atcm", "btcm"; ++ ti,sci = <&dmsc>; ++ ti,sci-dev-id = <121>; ++ ti,sci-proc-ids = <0x01 0xff>; ++ resets = <&k3_reset 121 1>; ++ firmware-name = "am62-wkup-r5f0_0-fw"; ++ ti,atcm-enable = <1>; ++ ti,btcm-enable = <1>; ++ ti,loczrama = <1>; ++ }; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,4 +1,7 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/* ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ ++ */ + + #include + +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-dahlia.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -185,7 +185,6 @@ + + /* Verdin SD_1 */ + &sdhci1 { +- ti,driver-strength-ohm = <33>; + status = "okay"; + }; + +@@ -214,6 +213,5 @@ + + /* Verdin UART_2 */ + &wkup_uart0 { +- /* FIXME: WKUP UART0 is used by DM firmware */ +- status = "reserved"; ++ status = "okay"; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-dev.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -206,7 +206,6 @@ + + /* Verdin SD_1 */ + &sdhci1 { +- ti,driver-strength-ohm = <33>; + status = "okay"; + }; + +@@ -235,6 +234,5 @@ + + /* Verdin UART_2 */ + &wkup_uart0 { +- /* FIXME: WKUP UART0 is used by DM firmware */ +- status = "reserved"; ++ status = "okay"; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -42,6 +42,22 @@ + usb1 = &usb1; + }; + ++ connector { ++ compatible = "gpio-usb-b-connector", "usb-b-connector"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_usb0_id>; ++ id-gpios = <&main_gpio1 19 GPIO_ACTIVE_HIGH>; ++ label = "USB_1"; ++ self-powered; ++ vbus-supply = <®_usb0_vbus>; ++ ++ port { ++ usb_dr_connector: endpoint { ++ remote-endpoint = <&usb0_ep>; ++ }; ++ }; ++ }; ++ + verdin_gpio_keys: gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; +@@ -151,6 +167,18 @@ + vin-supply = <®_sd_3v3_1v8>; + }; + ++ reg_usb0_vbus: regulator-usb0-vbus { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_usb0_en>; ++ enable-active-high; ++ /* Verdin USB_1_EN (SODIMM 155) */ ++ gpio = <&main_gpio1 50 GPIO_ACTIVE_HIGH>; ++ regulator-max-microvolt = <5000000>; ++ regulator-min-microvolt = <5000000>; ++ regulator-name = "USB_1_EN"; ++ }; ++ + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; +@@ -233,6 +261,13 @@ + >; + }; + ++ /* Verdin SPI_1 CS as GPIO */ ++ pinctrl_qspi1_io4_gpio: main-gpio0-7-default-pins { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x001c, PIN_INPUT, 7) /* (J23) OSPI0_D4.GPIO0_7 */ /* SODIMM 202 */ ++ >; ++ }; ++ + /* Verdin QSPI_1_CS# as GPIO (conflict with Verdin QSPI_1 interface) */ + pinctrl_qspi1_cs_gpio: main-gpio0-11-default-pins { + pinctrl-single,pins = < +@@ -429,6 +464,13 @@ + >; + }; + ++ /* Verdin USB_1_EN */ ++ pinctrl_usb0_en: main-gpio1-50-default-pins { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x0254, PIN_INPUT, 7) /* (C20) USB0_DRVVBUS.GPIO1_50 */ /* SODIMM 155 */ ++ >; ++ }; ++ + /* On-module I2C - PMIC_I2C */ + pinctrl_i2c0: main-i2c0-default-pins { + pinctrl-single,pins = < +@@ -599,12 +641,18 @@ + pinctrl_spi1: main-spi1-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0020, PIN_INPUT, 1) /* (J25) OSPI0_D5.SPI1_CLK */ /* SODIMM 196 */ +- AM62X_IOPAD(0x001c, PIN_INPUT, 1) /* (J23) OSPI0_D4.SPI1_CS0 */ /* SODIMM 202 */ + AM62X_IOPAD(0x0024, PIN_INPUT, 1) /* (H25) OSPI0_D6.SPI1_D0 */ /* SODIMM 200 */ + AM62X_IOPAD(0x0028, PIN_INPUT, 1) /* (J22) OSPI0_D7.SPI1_D1 */ /* SODIMM 198 */ + >; + }; + ++ /* Verdin SPI_1 CS */ ++ pinctrl_spi1_cs0: main-spi1-cs0-default-pins { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x001c, PIN_INPUT, 1) /* (J23) OSPI0_D4.SPI1_CS0 */ /* SODIMM 202 */ ++ >; ++ }; ++ + /* ETH_25MHz_CLK */ + pinctrl_eth_clock: main-system-clkout0-default-pins { + pinctrl-single,pins = < +@@ -647,13 +695,6 @@ + >; + }; + +- /* Verdin USB_1 */ +- pinctrl_usb0: main-usb0-default-pins { +- pinctrl-single,pins = < +- AM62X_IOPAD(0x0254, PIN_OUTPUT, 0) /* (C20) USB0_DRVVBUS */ /* SODIMM 155 */ +- >; +- }; +- + /* Verdin USB_2 */ + pinctrl_usb1: main-usb1-default-pins { + pinctrl-single,pins = < +@@ -1000,7 +1041,7 @@ + "", + "", + "SODIMM_17", +- "", /* 50 */ ++ "SODIMM_155", /* 50 */ + "", + "", + "", +@@ -1105,7 +1146,7 @@ + regulator-always-on; + regulator-boot-on; + regulator-max-microvolt = <850000>; +- regulator-min-microvolt = <850000>; ++ regulator-min-microvolt = <750000>; + regulator-name = "+VDD_CORE (PMIC BUCK1)"; + }; + +@@ -1278,7 +1319,7 @@ + /* Verdin SPI_1 */ + &main_spi1 { + pinctrl-names = "default"; +- pinctrl-0 = <&pinctrl_spi1>; ++ pinctrl-0 = <&pinctrl_spi1>, <&pinctrl_spi1_cs0>; + ti,pindir-d0-out-d1-in; + status = "disabled"; + }; +@@ -1394,7 +1435,6 @@ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdhci0>; + non-removable; +- ti,driver-strength-ohm = <50>; + status = "okay"; + }; + +@@ -1403,7 +1443,6 @@ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdhci1>; + disable-wp; +- ti,driver-strength-ohm = <50>; + vmmc-supply = <®_sdhc1_vmmc>; + vqmmc-supply = <®_sdhc1_vqmmc>; + status = "disabled"; +@@ -1415,11 +1454,16 @@ + status = "disabled"; + }; + +-/* TODO: role swich using ID pin */ + &usb0 { +- pinctrl-names = "default"; +- pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb0_id>; ++ adp-disable; ++ usb-role-switch; + status = "disabled"; ++ ++ port { ++ usb0_ep: endpoint { ++ remote-endpoint = <&usb_dr_connector>; ++ }; ++ }; + }; + + /* Verdin USB_2 */ +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-verdin-mallow.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-mallow.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-verdin-mallow.dtsi 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-mallow.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,188 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++/* ++ * Copyright 2023 Toradex ++ * ++ * Common dtsi for Verdin AM62 SoM on Mallow carrier board ++ * ++ * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 ++ * https://www.toradex.com/products/carrier-board/mallow-carrier-board ++ */ ++ ++#include ++ ++/ { ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_qspi1_clk_gpio>, ++ <&pinctrl_qspi1_cs_gpio>, ++ <&pinctrl_qspi1_io0_gpio>, ++ <&pinctrl_qspi1_io1_gpio>; ++ ++ /* SODIMM 52 - USER_LED_1_RED */ ++ led-0 { ++ color = ; ++ function = LED_FUNCTION_DEBUG; ++ function-enumerator = <1>; ++ gpios = <&main_gpio0 0 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ /* SODIMM 54 - USER_LED_1_GREEN */ ++ led-1 { ++ color = ; ++ function = LED_FUNCTION_DEBUG; ++ function-enumerator = <1>; ++ gpios = <&main_gpio0 11 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ /* SODIMM 56 - USER_LED_2_RED */ ++ led-2 { ++ color = ; ++ function = LED_FUNCTION_DEBUG; ++ function-enumerator = <2>; ++ gpios = <&main_gpio0 3 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ /* SODIMM 58 - USER_LED_2_GREEN */ ++ led-3 { ++ color = ; ++ function = LED_FUNCTION_DEBUG; ++ function-enumerator = <2>; ++ gpios = <&main_gpio0 4 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++}; ++ ++/* Verdin ETH */ ++&cpsw3g { ++ status = "okay"; ++}; ++ ++/* Verdin MDIO */ ++&cpsw3g_mdio { ++ status = "okay"; ++}; ++ ++/* Verdin ETH_1*/ ++&cpsw_port1 { ++ status = "okay"; ++}; ++ ++/* Verdin PWM_1 and PWM_2*/ ++&epwm0 { ++ status = "okay"; ++}; ++ ++/* Verdin PWM_3 DSI */ ++&epwm1 { ++ status = "okay"; ++}; ++ ++&main_gpio0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_ctrl_sleep_moci>, ++ <&pinctrl_gpio_1>, ++ <&pinctrl_gpio_2>, ++ <&pinctrl_gpio_3>, ++ <&pinctrl_gpio_4>; ++}; ++ ++/* Verdin I2C_1 */ ++&main_i2c1 { ++ status = "okay"; ++ ++ /* Temperature sensor */ ++ sensor@4f { ++ compatible = "ti,tmp1075"; ++ reg = <0x4f>; ++ }; ++ ++ /* EEPROM */ ++ eeprom@57 { ++ compatible = "st,24c02", "atmel,24c02"; ++ reg = <0x57>; ++ pagesize = <16>; ++ }; ++}; ++ ++/* Verdin I2C_2 DSI */ ++&main_i2c2 { ++ status = "okay"; ++}; ++ ++/* Verdin I2C_4 CSI */ ++&main_i2c3 { ++ status = "okay"; ++}; ++ ++/* Verdin CAN_1 */ ++&main_mcan0 { ++ status = "okay"; ++}; ++ ++/* Verdin SPI_1 */ ++&main_spi1 { ++ pinctrl-0 = <&pinctrl_spi1>, ++ <&pinctrl_spi1_cs0>, ++ <&pinctrl_qspi1_cs2_gpio>; ++ cs-gpios = <0>, <&main_gpio0 12 GPIO_ACTIVE_LOW>; ++ status = "okay"; ++}; ++ ++/* Verdin UART_3 */ ++&main_uart0 { ++ status = "okay"; ++}; ++ ++/* Verdin UART_1 */ ++&main_uart1 { ++ status = "okay"; ++}; ++ ++/* Verdin I2C_3_HDMI */ ++&mcu_i2c0 { ++ status = "okay"; ++}; ++ ++/* Verdin CAN_2 */ ++&mcu_mcan0 { ++ status = "okay"; ++}; ++ ++/* Verdin UART_4 */ ++&mcu_uart0 { ++ status = "okay"; ++}; ++ ++/* Verdin SD_1 */ ++&sdhci1 { ++ status = "okay"; ++}; ++ ++/* Verdin USB_1 */ ++&usbss0 { ++ status = "okay"; ++}; ++ ++&usb0 { ++ status = "okay"; ++}; ++ ++/* Verdin USB_2 */ ++&usbss1 { ++ status = "okay"; ++}; ++ ++&usb1 { ++ status = "okay"; ++}; ++ ++/* Verdin CTRL_WAKE1_MICO# */ ++&verdin_gpio_keys { ++ status = "okay"; ++}; ++ ++/* Verdin UART_2 */ ++&wkup_uart0 { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-wifi.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -26,7 +26,6 @@ + mmc-pwrseq = <&wifi_pwrseq>; + non-removable; + ti,fails-without-test-cd; +- ti,driver-strength-ohm = <50>; + vmmc-supply = <®_3v3>; + status = "okay"; + }; +@@ -35,5 +34,11 @@ + &main_uart5 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart5>; ++ uart-has-rtscts; + status = "okay"; ++ ++ bluetooth { ++ compatible = "nxp,88w8987-bt"; ++ fw-init-baudrate = <3000000>; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-verdin-yavia.dtsi b/arch/arm64/boot/dts/ti/k3-am62-verdin-yavia.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-verdin-yavia.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-verdin-yavia.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -207,6 +207,5 @@ + + /* Verdin UART_2 */ + &wkup_uart0 { +- /* FIXME: WKUP UART0 is used by DM firmware */ +- status = "reserved"; ++ status = "okay"; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,12 +1,15 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for AM625 SoC Family Wakeup Domain peripherals + * +- * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2020-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + ++#include ++ + &cbass_wakeup { + wkup_conf: syscon@43000000 { ++ bootph-all; + compatible = "syscon", "simple-mfd"; + reg = <0x00 0x43000000 0x00 0x20000>; + #address-cells = <1>; +@@ -14,19 +17,40 @@ + ranges = <0x0 0x00 0x43000000 0x20000>; + + chipid: chipid@14 { ++ bootph-all; + compatible = "ti,am654-chipid"; + reg = <0x14 0x4>; + }; + }; + +- wkup_uart0: serial@2b300000 { +- compatible = "ti,am64-uart", "ti,am654-uart"; +- reg = <0x00 0x2b300000 0x00 0x100>; +- interrupts = ; ++ target-module@2b300050 { ++ compatible = "ti,sysc-omap2", "ti,sysc"; ++ reg = <0x00 0x2b300050 0x00 0x4>, ++ <0x00 0x2b300054 0x00 0x4>, ++ <0x00 0x2b300058 0x00 0x4>; ++ reg-names = "rev", "sysc", "syss"; ++ ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP | ++ SYSC_OMAP2_SOFTRESET | ++ SYSC_OMAP2_AUTOIDLE)>; ++ ti,sysc-sidle = , ++ , ++ , ++ ; ++ ti,syss-mask = <1>; ++ ti,no-reset-on-init; + power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 114 0>; +- clock-names = "fclk"; +- status = "disabled"; ++ clock-names = "fck"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x00 0x2b300000 0x100000>; ++ ++ wkup_uart0: serial@0 { ++ compatible = "ti,am64-uart", "ti,am654-uart"; ++ reg = <0x0 0x100>; ++ interrupts = ; ++ status = "disabled"; ++ }; + }; + + wkup_i2c0: i2c@2b200000 { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra-gpio-fan.dtso b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra-gpio-fan.dtso +--- a/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra-gpio-fan.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62x-phyboard-lyra-gpio-fan.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,50 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/* ++ * Copyright (C) 2024 PHYTEC America LLC ++ * Author: Garrett Giordano ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++#include "k3-pinctrl.h" ++ ++&{/} { ++ fan: gpio-fan { ++ compatible = "gpio-fan"; ++ gpio-fan,speed-map = <0 0 8600 1>; ++ gpios = <&main_gpio0 40 GPIO_ACTIVE_LOW>; ++ #cooling-cells = <2>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&gpio_fan_pins_default>; ++ }; ++}; ++ ++&main_pmx0 { ++ gpio_fan_pins_default: gpio-fan-default-pins { ++ pinctrl-single,pins = < ++ AM62X_IOPAD(0x0a4, PIN_OUTPUT, 7) /* (M22) GPMC0_DIR.GPIO0_40 */ ++ >; ++ }; ++}; ++ ++&thermal_zones { ++ main0_thermal: main0-thermal { ++ trips { ++ main0_thermal_trip0: main0-thermal-trip { ++ temperature = <65000>; /* millicelsius */ ++ hysteresis = <2000>; /* millicelsius */ ++ type = "active"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&main0_thermal_trip0>; ++ cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Common dtsi for AM62x SK and derivatives + * +- * Copyright (C) 2021-2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2021-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +@@ -28,6 +28,7 @@ + }; + + memory@80000000 { ++ bootph-pre-ram; + device_type = "memory"; + /* 2G RAM */ + reg = <0x00000000 0x80000000 0x00000000 0x80000000>; +@@ -130,6 +131,7 @@ + &main_pmx0 { + /* First pad number is ALW package and second is AMC package */ + main_uart0_pins_default: main-uart0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14/A13) UART0_RXD */ + AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14/E11) UART0_TXD */ +@@ -137,6 +139,7 @@ + }; + + main_uart1_pins_default: main-uart1-default-pins { ++ bootph-pre-ram; + pinctrl-single,pins = < + AM62X_IOPAD(0x194, PIN_INPUT, 2) /* (B19/B18) MCASP0_AXR3.UART1_CTSn */ + AM62X_IOPAD(0x198, PIN_OUTPUT, 2) /* (A19/B17) MCASP0_AXR2.UART1_RTSn */ +@@ -167,6 +170,7 @@ + }; + + main_mmc0_pins_default: main-mmc0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3/V3) MMC0_CMD */ + AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1/Y1) MMC0_CLK */ +@@ -182,6 +186,7 @@ + }; + + main_mmc1_pins_default: main-mmc1-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x23c, PIN_INPUT, 0) /* (A21/C18) MMC1_CMD */ + AM62X_IOPAD(0x234, PIN_INPUT, 0) /* (B22/A20) MMC1_CLK */ +@@ -207,6 +212,7 @@ + }; + + main_rgmii1_pins_default: main-rgmii1-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM62X_IOPAD(0x14c, PIN_INPUT, 0) /* (AB17/W15) RGMII1_RD0 */ + AM62X_IOPAD(0x150, PIN_INPUT, 0) /* (AC17/Y16) RGMII1_RD1 */ +@@ -274,6 +280,7 @@ + + &mcu_pmx0 { + wkup_uart0_pins_default: wkup-uart0-default-pins { ++ bootph-pre-ram; + pinctrl-single,pins = < + AM62X_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C6/A7) WKUP_UART0_CTSn */ + AM62X_MCU_IOPAD(0x030, PIN_OUTPUT, 0) /* (A4/B4) WKUP_UART0_RTSn */ +@@ -285,12 +292,14 @@ + + &wkup_uart0 { + /* WKUP UART0 is used by DM firmware */ ++ bootph-pre-ram; + status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&wkup_uart0_pins_default>; + }; + + &main_uart0 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; +@@ -298,6 +307,7 @@ + + &main_uart1 { + /* Main UART1 is used by TIFS firmware */ ++ bootph-pre-ram; + status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; +@@ -389,39 +399,50 @@ + }; + }; + ++&main_i2c2 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c2_pins_default>; ++ clock-frequency = <400000>; ++}; ++ + &sdhci0 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc0_pins_default>; +- ti,driver-strength-ohm = <50>; + disable-wp; + }; + + &sdhci1 { + /* SD/MMC */ ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; +- ti,driver-strength-ohm = <50>; + disable-wp; + }; + + &cpsw3g { ++ bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&main_rgmii1_pins_default>; + }; + + &cpsw_port1 { ++ bootph-all; + phy-mode = "rgmii-rxid"; + phy-handle = <&cpsw3g_phy0>; + }; + + &cpsw3g_mdio { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_mdio1_pins_default>; + + cpsw3g_phy0: ethernet-phy@0 { ++ bootph-all; + reg = <0>; + ti,rx-internal-delay = ; + ti,fifo-depth = ; +@@ -437,6 +458,7 @@ + }; + + &usbss0 { ++ bootph-all; + status = "okay"; + ti,vbus-divider; + }; +@@ -447,6 +469,7 @@ + }; + + &usb0 { ++ bootph-all; + #address-cells = <1>; + #size-cells = <0>; + usb-role-switch; +@@ -501,3 +524,12 @@ + }; + }; + }; ++ ++/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */ ++&mcu_gpio0 { ++ status = "reserved"; ++}; ++ ++&mcu_gpio_intr { ++ status = "reserved"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-imx219.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-imx219.dtso +--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-imx219.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-imx219.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,84 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * IMX219 (RPi v2) Camera Module ++ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++&{/} { ++ clk_imx219_fixed: imx219-xclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ }; ++}; ++ ++&main_i2c2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ i2c-switch@71 { ++ compatible = "nxp,pca9543"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x71>; ++ ++ /* CAM port */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ ov5640: camera@10 { ++ compatible = "sony,imx219"; ++ reg = <0x10>; ++ ++ clocks = <&clk_imx219_fixed>; ++ clock-names = "xclk"; ++ ++ reset-gpios = <&exp1 13 GPIO_ACTIVE_HIGH>; ++ ++ port { ++ csi2_cam0: endpoint { ++ remote-endpoint = <&csi2rx0_in_sensor>; ++ link-frequencies = /bits/ 64 <456000000>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&cdns_csi2rx0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "okay"; ++ ++ csi2rx0_in_sensor: endpoint { ++ remote-endpoint = <&csi2_cam0>; ++ bus-type = <4>; /* CSI2 DPHY. */ ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++&ti_csi2rx0 { ++ status = "okay"; ++}; ++ ++&dphy0 { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-ov5640.dtso +--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-ov5640.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-ov5640.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,82 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * ALINX AN5641 & Digilent PCam 5C - OV5640 camera module ++ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++&{/} { ++ clk_ov5640_fixed: ov5640-xclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <12000000>; ++ }; ++}; ++ ++&main_i2c2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ i2c-switch@71 { ++ compatible = "nxp,pca9543"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x71>; ++ ++ /* CAM port */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ ov5640: camera@3c { ++ compatible = "ovti,ov5640"; ++ reg = <0x3c>; ++ ++ clocks = <&clk_ov5640_fixed>; ++ clock-names = "xclk"; ++ powerdown-gpios = <&exp1 13 GPIO_ACTIVE_LOW>; ++ ++ port { ++ csi2_cam0: endpoint { ++ remote-endpoint = <&csi2rx0_in_sensor>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&cdns_csi2rx0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "okay"; ++ ++ csi2rx0_in_sensor: endpoint { ++ remote-endpoint = <&csi2_cam0>; ++ bus-type = <4>; /* CSI2 DPHY. */ ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++&ti_csi2rx0 { ++ status = "okay"; ++}; ++ ++&dphy0 { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-tevi-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-tevi-ov5640.dtso +--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-tevi-ov5640.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-tevi-ov5640.dtso 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,82 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Technexion TEVI-OV5640-*-RPI - OV5640 camera module ++ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++ ++&{/} { ++ clk_ov5640_fixed: ov5640-xclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ }; ++}; ++ ++&main_i2c2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ i2c-switch@71 { ++ compatible = "nxp,pca9543"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x71>; ++ ++ /* CAM port */ ++ i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ ++ ov5640: camera@3c { ++ compatible = "ovti,ov5640"; ++ reg = <0x3c>; ++ ++ clocks = <&clk_ov5640_fixed>; ++ clock-names = "xclk"; ++ powerdown-gpios = <&exp1 13 GPIO_ACTIVE_LOW>; ++ ++ port { ++ csi2_cam0: endpoint { ++ remote-endpoint = <&csi2rx0_in_sensor>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&cdns_csi2rx0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "okay"; ++ ++ csi2rx0_in_sensor: endpoint { ++ remote-endpoint = <&csi2_cam0>; ++ bus-type = <4>; /* CSI2 DPHY. */ ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++&ti_csi2rx0 { ++ status = "okay"; ++}; ++ ++&dphy0 { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts +--- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts 2024-03-28 11:26:09.893017428 -0400 +@@ -35,6 +35,7 @@ + }; + + memory@80000000 { ++ bootph-all; + device_type = "memory"; + /* 2G RAM */ + reg = <0x00000000 0x80000000 0x00000000 0x80000000>; +@@ -108,6 +109,7 @@ + + evm_12v0: regulator-0 { + /* main DC jack */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "evm_12v0"; + regulator-min-microvolt = <12000000>; +@@ -129,6 +131,7 @@ + + vsys_3v3: regulator-2 { + /* output of LM5140 */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vsys_3v3"; + regulator-min-microvolt = <3300000>; +@@ -140,6 +143,7 @@ + + vdd_mmc1: regulator-3 { + /* TPS2051BD */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vdd_mmc1"; + regulator-min-microvolt = <3300000>; +@@ -161,6 +165,7 @@ + }; + + vtt_supply: regulator-5 { ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vtt"; + pinctrl-names = "default"; +@@ -251,6 +256,7 @@ + }; + + main_uart0_pins_default: main-uart0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x0238, PIN_INPUT, 0) /* (B16) UART0_CTSn */ + AM64X_IOPAD(0x023c, PIN_OUTPUT, 0) /* (A16) UART0_RTSn */ +@@ -269,6 +275,7 @@ + }; + + main_i2c0_pins_default: main-i2c0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x0260, PIN_INPUT_PULLUP, 0) /* (A18) I2C0_SCL */ + AM64X_IOPAD(0x0264, PIN_INPUT_PULLUP, 0) /* (B18) I2C0_SDA */ +@@ -276,6 +283,7 @@ + }; + + main_i2c1_pins_default: main-i2c1-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x0268, PIN_INPUT_PULLUP, 0) /* (C18) I2C1_SCL */ + AM64X_IOPAD(0x026c, PIN_INPUT_PULLUP, 0) /* (B19) I2C1_SDA */ +@@ -283,6 +291,7 @@ + }; + + mdio1_pins_default: mdio1-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x01fc, PIN_OUTPUT, 4) /* (R2) PRG0_PRU1_GPO19.MDIO0_MDC */ + AM64X_IOPAD(0x01f8, PIN_INPUT, 4) /* (P5) PRG0_PRU1_GPO18.MDIO0_MDIO */ +@@ -290,6 +299,7 @@ + }; + + rgmii1_pins_default: rgmii1-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x01cc, PIN_INPUT, 4) /* (W5) PRG0_PRU1_GPO7.RGMII1_RD0 */ + AM64X_IOPAD(0x01d4, PIN_INPUT, 4) /* (Y5) PRG0_PRU1_GPO9.RGMII1_RD1 */ +@@ -307,6 +317,7 @@ + }; + + rgmii2_pins_default: rgmii2-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x0108, PIN_INPUT, 4) /* (W11) PRG1_PRU1_GPO0.RGMII2_RD0 */ + AM64X_IOPAD(0x010c, PIN_INPUT, 4) /* (V11) PRG1_PRU1_GPO1.RGMII2_RD1 */ +@@ -324,6 +335,7 @@ + }; + + main_usb0_pins_default: main-usb0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (E19) USB0_DRVVBUS */ + >; +@@ -366,6 +378,7 @@ + }; + + ddr_vtt_pins_default: ddr-vtt-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x0030, PIN_OUTPUT_PULLUP, 7) /* (L18) OSPI0_CSN1.GPIO0_12 */ + >; +@@ -373,6 +386,7 @@ + }; + + &main_uart0 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; +@@ -387,11 +401,21 @@ + }; + + &main_i2c0 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c0_pins_default>; + clock-frequency = <400000>; + ++ gpio@38 { ++ /* TCA9554 */ ++ compatible = "nxp,pca9554"; ++ reg = <0x38>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ gpio-line-names = "HSE_DETECT"; ++ }; ++ + eeprom@50 { + /* AT24CM01 */ + compatible = "atmel,24c1024"; +@@ -400,12 +424,14 @@ + }; + + &main_i2c1 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c1_pins_default>; + clock-frequency = <400000>; + + exp1: gpio@22 { ++ bootph-all; + compatible = "ti,tca6424"; + reg = <0x22>; + gpio-controller; +@@ -438,11 +464,19 @@ + }; + }; + +-/* mcu_gpio0 is reserved for mcu firmware usage */ ++&main_gpio0 { ++ bootph-all; ++}; ++ ++/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */ + &mcu_gpio0 { + status = "reserved"; + }; + ++&mcu_gpio_intr { ++ status = "reserved"; ++}; ++ + &main_spi0 { + status = "okay"; + pinctrl-names = "default"; +@@ -457,30 +491,33 @@ + }; + }; + ++/* eMMC */ + &sdhci0 { +- /* emmc */ +- bus-width = <8>; ++ status = "okay"; + non-removable; + ti,driver-strength-ohm = <50>; + disable-wp; ++ bootph-all; + }; + ++/* SD/MMC */ + &sdhci1 { +- /* SD/MMC */ ++ bootph-all; ++ status = "okay"; + vmmc-supply = <&vdd_mmc1>; + pinctrl-names = "default"; +- bus-width = <4>; + pinctrl-0 = <&main_mmc1_pins_default>; +- ti,driver-strength-ohm = <50>; + disable-wp; + }; + + &usbss0 { ++ bootph-all; + ti,vbus-divider; + ti,usb2-only; + }; + + &usb0 { ++ bootph-all; + dr_mode = "otg"; + maximum-speed = "high-speed"; + pinctrl-names = "default"; +@@ -488,11 +525,13 @@ + }; + + &cpsw3g { ++ bootph-all; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins_default>, <&rgmii2_pins_default>; + }; + + &cpsw_port1 { ++ bootph-all; + phy-mode = "rgmii-rxid"; + phy-handle = <&cpsw3g_phy0>; + }; +@@ -503,11 +542,13 @@ + }; + + &cpsw3g_mdio { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mdio1_pins_default>; + + cpsw3g_phy0: ethernet-phy@0 { ++ bootph-all; + reg = <0>; + ti,rx-internal-delay = ; + ti,fifo-depth = ; +@@ -617,25 +658,25 @@ + }; + + &main_r5fss0_core0 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core0>; + memory-region = <&main_r5fss0_core0_dma_memory_region>, + <&main_r5fss0_core0_memory_region>; + }; + + &main_r5fss0_core1 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core1>; + memory-region = <&main_r5fss0_core1_dma_memory_region>, + <&main_r5fss0_core1_memory_region>; + }; + + &main_r5fss1_core0 { +- mboxes = <&mailbox0_cluster4>, <&mbox_main_r5fss1_core0>; ++ mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core0>; + memory-region = <&main_r5fss1_core0_dma_memory_region>, + <&main_r5fss1_core0_memory_region>; + }; + + &main_r5fss1_core1 { +- mboxes = <&mailbox0_cluster4>, <&mbox_main_r5fss1_core1>; ++ mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core1>; + memory-region = <&main_r5fss1_core1_dma_memory_region>, + <&main_r5fss1_core1_memory_region>; + }; +@@ -660,12 +701,6 @@ + phys = <&serdes0_pcie_link>; + phy-names = "pcie-phy"; + num-lanes = <1>; +-}; +- +-&pcie0_ep { +- phys = <&serdes0_pcie_link>; +- phy-names = "pcie-phy"; +- num-lanes = <1>; + }; + + &ecap0 { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts +--- a/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -159,6 +159,15 @@ + >; + }; + ++ main_spi0_pins_default: main-spi0-default-pins { ++ pinctrl-single,pins = < ++ AM64X_IOPAD(0x020c, PIN_OUTPUT, 7) /* (C13) SPI0_CS1.GPIO1_43 */ ++ AM64X_IOPAD(0x0210, PIN_INPUT, 0) /* (D13) SPI0_CLK */ ++ AM64X_IOPAD(0x0214, PIN_OUTPUT, 0) /* (A13) SPI0_D0 */ ++ AM64X_IOPAD(0x0218, PIN_INPUT, 0) /* (A14) SPI0_D1 */ ++ >; ++ }; ++ + main_uart0_pins_default: main-uart0-default-pins { + pinctrl-single,pins = < + AM64X_IOPAD(0x0230, PIN_INPUT, 0) /* (D15) UART0_RXD */ +@@ -248,6 +257,20 @@ + phys = <&can_tc2>; + }; + ++&main_spi0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_spi0_pins_default>; ++ cs-gpios = <0>, <&main_gpio1 43 GPIO_ACTIVE_LOW>; ++ ti,pindir-d0-out-d1-in; ++ ++ tpm@1 { ++ compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; ++ reg = <1>; ++ spi-max-frequency = <10000000>; ++ }; ++}; ++ + &main_uart0 { + status = "okay"; + pinctrl-names = "default"; +@@ -264,11 +287,11 @@ + }; + + &sdhci1 { ++ status = "okay"; + vmmc-supply = <&vcc_3v3_mmc>; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; + bus-width = <4>; +- ti,driver-strength-ohm = <50>; + disable-wp; + no-1-8-v; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts +--- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -34,6 +34,7 @@ + }; + + memory@80000000 { ++ bootph-pre-ram; + device_type = "memory"; + /* 2G RAM */ + reg = <0x00000000 0x80000000 0x00000000 0x80000000>; +@@ -107,6 +108,7 @@ + + vusb_main: regulator-0 { + /* USB MAIN INPUT 5V DC */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vusb_main5v0"; + regulator-min-microvolt = <5000000>; +@@ -117,6 +119,7 @@ + + vcc_3v3_sys: regulator-1 { + /* output of LP8733xx */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vcc_3v3_sys"; + regulator-min-microvolt = <3300000>; +@@ -128,6 +131,7 @@ + + vdd_mmc1: regulator-2 { + /* TPS2051BD */ ++ bootph-all; + compatible = "regulator-fixed"; + regulator-name = "vdd_mmc1"; + regulator-min-microvolt = <3300000>; +@@ -234,6 +238,7 @@ + + &main_pmx0 { + main_mmc1_pins_default: main-mmc1-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x029c, PIN_INPUT_PULLUP, 0) /* (C20) MMC1_SDWP */ + AM64X_IOPAD(0x0298, PIN_INPUT_PULLUP, 0) /* (D19) MMC1_SDCD */ +@@ -248,6 +253,7 @@ + }; + + main_uart0_pins_default: main-uart0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x0238, PIN_INPUT, 0) /* (B16) UART0_CTSn */ + AM64X_IOPAD(0x023c, PIN_OUTPUT, 0) /* (A16) UART0_RTSn */ +@@ -257,6 +263,7 @@ + }; + + main_uart1_pins_default: main-uart1-default-pins { ++ bootph-pre-ram; + pinctrl-single,pins = < + AM64X_IOPAD(0x0248, PIN_INPUT, 0) /* (D16) UART1_CTSn */ + AM64X_IOPAD(0x024c, PIN_OUTPUT, 0) /* (E16) UART1_RTSn */ +@@ -266,12 +273,14 @@ + }; + + main_usb0_pins_default: main-usb0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (E19) USB0_DRVVBUS */ + >; + }; + + main_i2c0_pins_default: main-i2c0-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x0260, PIN_INPUT_PULLUP, 0) /* (A18) I2C0_SCL */ + AM64X_IOPAD(0x0264, PIN_INPUT_PULLUP, 0) /* (B18) I2C0_SDA */ +@@ -279,6 +288,7 @@ + }; + + main_i2c1_pins_default: main-i2c1-default-pins { ++ bootph-all; + pinctrl-single,pins = < + AM64X_IOPAD(0x0268, PIN_INPUT_PULLUP, 0) /* (C18) I2C1_SCL */ + AM64X_IOPAD(0x026c, PIN_INPUT_PULLUP, 0) /* (B19) I2C1_SDA */ +@@ -367,6 +377,7 @@ + }; + + &main_uart0 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; +@@ -375,12 +386,14 @@ + + &main_uart1 { + /* main_uart1 is reserved for firmware usage */ ++ bootph-pre-ram; + status = "reserved"; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart1_pins_default>; + }; + + &main_i2c0 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c0_pins_default>; +@@ -393,12 +406,14 @@ + }; + + &main_i2c1 { ++ bootph-all; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_i2c1_pins_default>; + clock-frequency = <400000>; + + exp1: gpio@70 { ++ bootph-all; + compatible = "nxp,pca9538"; + reg = <0x70>; + gpio-controller; +@@ -418,12 +433,17 @@ + }; + }; + +-/* mcu_gpio0 is reserved for mcu firmware usage */ ++/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */ + &mcu_gpio0 { + status = "reserved"; + }; + ++&mcu_gpio_intr { ++ status = "reserved"; ++}; ++ + &sdhci0 { ++ status = "okay"; + vmmc-supply = <&wlan_en>; + bus-width = <4>; + non-removable; +@@ -443,22 +463,33 @@ + }; + }; + ++/* SD/MMC */ + &sdhci1 { +- /* SD/MMC */ ++ bootph-all; ++ status = "okay"; + vmmc-supply = <&vdd_mmc1>; + pinctrl-names = "default"; +- bus-width = <4>; + pinctrl-0 = <&main_mmc1_pins_default>; +- ti,driver-strength-ohm = <50>; + disable-wp; + }; + + &serdes_ln_ctrl { ++ bootph-all; + idle-states = ; + }; + ++&serdes_refclk { ++ bootph-all; ++}; ++ ++&serdes_wiz0 { ++ bootph-all; ++}; ++ + &serdes0 { ++ bootph-all; + serdes0_usb_link: phy@0 { ++ bootph-all; + reg = <0>; + cdns,num-lanes = <1>; + #phy-cells = <0>; +@@ -468,10 +499,12 @@ + }; + + &usbss0 { ++ bootph-all; + ti,vbus-divider; + }; + + &usb0 { ++ bootph-all; + dr_mode = "host"; + maximum-speed = "super-speed"; + pinctrl-names = "default"; +@@ -611,25 +644,25 @@ + }; + + &main_r5fss0_core0 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core0>; + memory-region = <&main_r5fss0_core0_dma_memory_region>, + <&main_r5fss0_core0_memory_region>; + }; + + &main_r5fss0_core1 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core1>; + memory-region = <&main_r5fss0_core1_dma_memory_region>, + <&main_r5fss0_core1_memory_region>; + }; + + &main_r5fss1_core0 { +- mboxes = <&mailbox0_cluster4>, <&mbox_main_r5fss1_core0>; ++ mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core0>; + memory-region = <&main_r5fss1_core0_dma_memory_region>, + <&main_r5fss1_core0_memory_region>; + }; + + &main_r5fss1_core1 { +- mboxes = <&mailbox0_cluster4>, <&mbox_main_r5fss1_core1>; ++ mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core1>; + memory-region = <&main_r5fss1_core1_dma_memory_region>, + <&main_r5fss1_core1_memory_region>; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -85,6 +85,15 @@ + no-map; + }; + }; ++ ++ reg_1v8: regulator-1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "V_1V8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; + }; + + &main_i2c0 { +@@ -96,11 +105,13 @@ + tmp1075: temperature-sensor@4a { + compatible = "ti,tmp1075"; + reg = <0x4a>; ++ vs-supply = <®_1v8>; + }; + + eeprom0: eeprom@50 { + compatible = "st,24c02", "atmel,24c02"; + reg = <0x50>; ++ vcc-supply = <®_1v8>; + pagesize = <16>; + read-only; + }; +@@ -114,6 +125,7 @@ + eeprom1: eeprom@54 { + compatible = "st,24c64", "atmel,24c64"; + reg = <0x54>; ++ vcc-supply = <®_1v8>; + pagesize = <32>; + }; + }; +@@ -207,6 +219,7 @@ + }; + + &sdhci0 { ++ status = "okay"; + non-removable; + disable-wp; + no-sdio; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts +--- a/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am642-tqma64xxl-mbax4xxl.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -8,6 +8,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -19,6 +20,7 @@ + compatible = "tq,am642-tqma6442l-mbax4xxl", "tq,am642-tqma6442l", + "ti,am642"; + model = "TQ-Systems TQMa64xxL SoM on MBax4xxL carrier board"; ++ chassis-type = "embedded"; + + aliases { + ethernet0 = &cpsw_port1; +@@ -58,12 +60,14 @@ + pinctrl-0 = <&mcu_gpio_leds_pins>; + + led-0 { +- label = "led0"; + gpios = <&mcu_gpio0 8 GPIO_ACTIVE_HIGH>; ++ color = ; ++ function = LED_FUNCTION_INDICATOR; + }; + led-1 { +- label = "led1"; + gpios = <&mcu_gpio0 9 GPIO_ACTIVE_HIGH>; ++ color = ; ++ function = LED_FUNCTION_INDICATOR; + }; + }; + +@@ -170,7 +174,8 @@ + + &main_gpio1 { + pinctrl-names = "default"; +- pinctrl-0 = <&main_gpio1_hog_pins>; ++ pinctrl-0 = <&main_gpio1_hog_pins>, ++ <&main_gpio1_pru_pins>; + gpio-line-names = + "", "", "", "", /* 0-3 */ + "", "", "", "", /* 4-7 */ +@@ -417,10 +422,8 @@ + cd-gpios = <&main_gpio1 77 GPIO_ACTIVE_LOW>; + disable-wp; + no-mmc; +- ti,driver-strength-ohm = <50>; + ti,fails-without-test-cd; + /* Enabled by overlay */ +- status = "disabled"; + }; + + &tscadc0 { +@@ -545,6 +548,79 @@ + >; + }; + ++ main_gpio1_pru_pins: main-gpio1-pru-pins { ++ pinctrl-single,pins = < ++ /* (Y1) PRG0_PRU0_GPO0.GPIO1_0 */ ++ AM64X_IOPAD(0x0160, PIN_INPUT, 7) ++ /* (R4) PRG0_PRU0_GPO1.GPIO1_1 */ ++ AM64X_IOPAD(0x0164, PIN_INPUT, 7) ++ /* (U2) PRG0_PRU0_GPO2.GPIO1_2 */ ++ AM64X_IOPAD(0x0168, PIN_INPUT, 7) ++ /* (V2) PRG0_PRU0_GPO3.GPIO1_3 */ ++ AM64X_IOPAD(0x016c, PIN_INPUT, 7) ++ /* (AA2) PRG0_PRU0_GPO4.GPIO1_4 */ ++ AM64X_IOPAD(0x0170, PIN_INPUT, 7) ++ /* (R3) PRG0_PRU0_GPO5.GPIO1_5 */ ++ AM64X_IOPAD(0x0174, PIN_INPUT, 7) ++ /* (T3) PRG0_PRU0_GPO6.GPIO1_6 */ ++ AM64X_IOPAD(0x0178, PIN_INPUT, 7) ++ /* (T1) PRG0_PRU0_GPO7.GPIO1_7 */ ++ AM64X_IOPAD(0x017c, PIN_INPUT, 7) ++ /* (T2) PRG0_PRU0_GPO8.GPIO1_8 */ ++ AM64X_IOPAD(0x0180, PIN_INPUT, 7) ++ /* (Y3) PRG0_PRU0_GPO11.GPIO1_11 */ ++ AM64X_IOPAD(0x018c, PIN_INPUT, 7) ++ /* (AA3) PRG0_PRU0_GPO12.GPIO1_12 */ ++ AM64X_IOPAD(0x0190, PIN_INPUT, 7) ++ /* (R6) PRG0_PRU0_GPO13.GPIO1_13 */ ++ AM64X_IOPAD(0x0194, PIN_INPUT, 7) ++ /* (V4) PRG0_PRU0_GPO14.GPIO1_14 */ ++ AM64X_IOPAD(0x0198, PIN_INPUT, 7) ++ /* (T5) PRG0_PRU0_GPO15.GPIO1_15 */ ++ AM64X_IOPAD(0x019c, PIN_INPUT, 7) ++ /* (U4) PRG0_PRU0_GPO16.GPIO1_16 */ ++ AM64X_IOPAD(0x01a0, PIN_INPUT, 7) ++ /* (U1) PRG0_PRU0_GPO17.GPIO1_17 */ ++ AM64X_IOPAD(0x01a4, PIN_INPUT, 7) ++ /* (V1) PRG0_PRU0_GPO18.GPIO1_18 */ ++ AM64X_IOPAD(0x01a8, PIN_INPUT, 7) ++ /* (W1) PRG0_PRU0_GPO19.GPIO1_19 */ ++ AM64X_IOPAD(0x01ac, PIN_INPUT, 7) ++ /* (Y2) PRG0_PRU1_GPO0.GPIO1_20 */ ++ AM64X_IOPAD(0x01b0, PIN_INPUT, 7) ++ /* (W2) PRG0_PRU1_GPO1.GPIO1_21 */ ++ AM64X_IOPAD(0x01b4, PIN_INPUT, 7) ++ /* (V3) PRG0_PRU1_GPO2.GPIO1_22 */ ++ AM64X_IOPAD(0x01b8, PIN_INPUT, 7) ++ /* (T4) PRG0_PRU1_GPO3.GPIO1_23 */ ++ AM64X_IOPAD(0x01bc, PIN_INPUT, 7) ++ /* (W3) PRG0_PRU1_GPO4.GPIO1_24 */ ++ AM64X_IOPAD(0x01c0, PIN_INPUT, 7) ++ /* (P4) PRG0_PRU1_GPO5.GPIO1_25 */ ++ AM64X_IOPAD(0x01c4, PIN_INPUT, 7) ++ /* (R5) PRG0_PRU1_GPO6.GPIO1_26 */ ++ AM64X_IOPAD(0x01c8, PIN_INPUT, 7) ++ /* (R1) PRG0_PRU1_GPO8.GPIO1_28 */ ++ AM64X_IOPAD(0x01d0, PIN_INPUT, 7) ++ /* (W4) PRG0_PRU1_GPO11.GPIO1_31 */ ++ AM64X_IOPAD(0x01dc, PIN_INPUT, 7) ++ /* (Y4) PRG0_PRU1_GPO12.GPIO1_32 */ ++ AM64X_IOPAD(0x01e0, PIN_INPUT, 7) ++ /* (T6) PRG0_PRU1_GPO13.GPIO1_33 */ ++ AM64X_IOPAD(0x01e4, PIN_INPUT, 7) ++ /* (U6) PRG0_PRU1_GPO14.GPIO1_34 */ ++ AM64X_IOPAD(0x01e8, PIN_INPUT, 7) ++ /* (U5) PRG0_PRU1_GPO15.GPIO1_35 */ ++ AM64X_IOPAD(0x01ec, PIN_INPUT, 7) ++ /* (AA4) PRG0_PRU1_GPO16.GPIO1_36 */ ++ AM64X_IOPAD(0x01f0, PIN_INPUT, 7) ++ /* (P2) PRG0_MDIO0_MDIO.GPIO1_40 */ ++ AM64X_IOPAD(0x0200, PIN_INPUT, 7) ++ /* (P3) PRG0_MDIO0_MDC.GPIO1_41 */ ++ AM64X_IOPAD(0x0204, PIN_INPUT, 7) ++ >; ++ }; ++ + main_mcan0_pins: main-mcan0-pins { + pinctrl-single,pins = < + /* (B17) MCAN0_RX */ +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am64.dtsi b/arch/arm64/boot/dts/ti/k3-am64.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am64.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am64.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -47,6 +47,7 @@ + }; + + cbass_main: bus@f4000 { ++ bootph-all; + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; +@@ -85,6 +86,7 @@ + <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>; + + cbass_mcu: bus@4000000 { ++ bootph-all; + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -38,6 +38,7 @@ + }; + + main_conf: syscon@43000000 { ++ bootph-all; + compatible = "ti,j721e-system-controller", "syscon", "simple-mfd"; + reg = <0x0 0x43000000 0x0 0x20000>; + #address-cells = <1>; +@@ -45,14 +46,16 @@ + ranges = <0x0 0x0 0x43000000 0x20000>; + + chipid@14 { ++ bootph-all; + compatible = "ti,am654-chipid"; + reg = <0x00000014 0x4>; + }; + +- serdes_ln_ctrl: mux-controller { +- compatible = "mmio-mux"; ++ serdes_ln_ctrl: mux-controller@4080 { ++ compatible = "reg-mux"; ++ reg = <0x4080 0x4>; + #mux-control-cells = <1>; +- mux-reg-masks = <0x4080 0x3>; /* SERDES0 lane0 select */ ++ mux-reg-masks = <0x0 0x3>; /* SERDES0 lane0 select */ + }; + + phy_gmii_sel: phy@4044 { +@@ -61,7 +64,7 @@ + #phy-cells = <1>; + }; + +- epwm_tbclk: clock-controller@4140 { ++ epwm_tbclk: clock-controller@4130 { + compatible = "ti,am64-epwm-tbclk"; + reg = <0x4130 0x4>; + #clock-cells = <1>; +@@ -96,7 +99,8 @@ + }; + + dmss: bus@48000000 { +- compatible = "simple-mfd"; ++ bootph-all; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + dma-ranges; +@@ -105,6 +109,7 @@ + ti,sci-dev-id = <25>; + + secure_proxy_main: mailbox@4d000000 { ++ bootph-all; + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; +@@ -134,8 +139,13 @@ + <0x00 0x4c000000 0x00 0x20000>, + <0x00 0x4a820000 0x00 0x20000>, + <0x00 0x4aa40000 0x00 0x20000>, +- <0x00 0x4bc00000 0x00 0x100000>; +- reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt"; ++ <0x00 0x4bc00000 0x00 0x100000>, ++ <0x00 0x48600000 0x00 0x8000>, ++ <0x00 0x484a4000 0x00 0x2000>, ++ <0x00 0x484c2000 0x00 0x2000>, ++ <0x00 0x48420000 0x00 0x2000>; ++ reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "bchan"; + msi-parent = <&inta_main_dmss>; + #dma-cells = <3>; + +@@ -151,8 +161,13 @@ + reg = <0x00 0x485c0000 0x00 0x100>, + <0x00 0x4a800000 0x00 0x20000>, + <0x00 0x4aa00000 0x00 0x40000>, +- <0x00 0x4b800000 0x00 0x400000>; +- reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt"; ++ <0x00 0x4b800000 0x00 0x400000>, ++ <0x00 0x485e0000 0x00 0x20000>, ++ <0x00 0x484a0000 0x00 0x4000>, ++ <0x00 0x484c0000 0x00 0x2000>, ++ <0x00 0x48430000 0x00 0x4000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "rflow"; + msi-parent = <&inta_main_dmss>; + #dma-cells = <2>; + +@@ -188,6 +203,7 @@ + }; + + dmsc: system-controller@44043000 { ++ bootph-all; + compatible = "ti,k2g-sci"; + ti,host-id = <12>; + mbox-names = "rx", "tx"; +@@ -197,22 +213,26 @@ + reg = <0x00 0x44043000 0x00 0xfe0>; + + k3_pds: power-controller { ++ bootph-all; + compatible = "ti,sci-pm-domain"; + #power-domain-cells = <2>; + }; + + k3_clks: clock-controller { ++ bootph-all; + compatible = "ti,k2g-sci-clk"; + #clock-cells = <2>; + }; + + k3_reset: reset-controller { ++ bootph-all; + compatible = "ti,sci-reset"; + #reset-cells = <2>; + }; + }; + + main_pmx0: pinctrl@f4000 { ++ bootph-all; + compatible = "pinctrl-single"; + reg = <0x00 0xf4000 0x00 0x2d0>; + #pinctrl-cells = <1>; +@@ -221,6 +241,7 @@ + }; + + main_timer0: timer@2400000 { ++ bootph-all; + compatible = "ti,am654-timer"; + reg = <0x00 0x2400000 0x00 0x400>; + interrupts = ; +@@ -365,6 +386,7 @@ + }; + + main_esm: esm@420000 { ++ bootph-pre-ram; + compatible = "ti,j721e-esm"; + reg = <0x00 0x420000 0x00 0x1000>; + ti,esm-pins = <160>, <161>; +@@ -605,13 +627,19 @@ + power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 57 0>, <&k3_clks 57 1>; + clock-names = "clk_ahb", "clk_xin"; ++ bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; ++ ti,clkbuf-sel = <0x7>; + ti,trm-icp = <0x2>; + ti,otap-del-sel-legacy = <0x0>; + ti,otap-del-sel-mmc-hs = <0x0>; + ti,otap-del-sel-ddr52 = <0x6>; + ti,otap-del-sel-hs200 = <0x7>; ++ ti,itap-del-sel-legacy = <0x10>; ++ ti,itap-del-sel-mmc-hs = <0xa>; ++ ti,itap-del-sel-ddr52 = <0x3>; ++ status = "disabled"; + }; + + sdhci1: mmc@fa00000 { +@@ -621,15 +649,20 @@ + power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 58 3>, <&k3_clks 58 4>; + clock-names = "clk_ahb", "clk_xin"; +- ti,trm-icp = <0x2>; ++ bus-width = <4>; ++ ti,clkbuf-sel = <0x7>; + ti,otap-del-sel-legacy = <0x0>; +- ti,otap-del-sel-sd-hs = <0xf>; ++ ti,otap-del-sel-sd-hs = <0x0>; + ti,otap-del-sel-sdr12 = <0xf>; + ti,otap-del-sel-sdr25 = <0xf>; + ti,otap-del-sel-sdr50 = <0xc>; + ti,otap-del-sel-sdr104 = <0x6>; + ti,otap-del-sel-ddr50 = <0x9>; +- ti,clkbuf-sel = <0x7>; ++ ti,itap-del-sel-legacy = <0x0>; ++ ti,itap-del-sel-sd-hs = <0x0>; ++ ti,itap-del-sel-sdr12 = <0x0>; ++ ti,itap-del-sel-sdr25 = <0x0>; ++ status = "disabled"; + }; + + cpsw3g: ethernet@8000000 { +@@ -1018,25 +1051,6 @@ + status = "disabled"; + }; + +- pcie0_ep: pcie-ep@f102000 { +- compatible = "ti,am64-pcie-ep", "ti,j721e-pcie-ep"; +- reg = <0x00 0x0f102000 0x00 0x1000>, +- <0x00 0x0f100000 0x00 0x400>, +- <0x00 0x0d000000 0x00 0x00800000>, +- <0x00 0x68000000 0x00 0x08000000>; +- reg-names = "intd_cfg", "user_cfg", "reg", "mem"; +- interrupt-names = "link_state"; +- interrupts = ; +- ti,syscon-pcie-ctrl = <&main_conf 0x4070>; +- max-link-speed = <2>; +- num-lanes = <1>; +- power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 114 0>; +- clock-names = "fck"; +- max-functions = /bits/ 8 <1>; +- status = "disabled"; +- }; +- + epwm0: pwm@23000000 { + compatible = "ti,am64-epwm", "ti,am3352-ehrpwm"; + #pwm-cells = <3>; +@@ -1158,21 +1172,21 @@ + }; + + main_rti0: watchdog@e000000 { +- compatible = "ti,j7-rti-wdt"; +- reg = <0x00 0xe000000 0x00 0x100>; +- clocks = <&k3_clks 125 0>; +- power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>; +- assigned-clocks = <&k3_clks 125 0>; +- assigned-clock-parents = <&k3_clks 125 2>; ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0xe000000 0x00 0x100>; ++ clocks = <&k3_clks 125 0>; ++ power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 125 0>; ++ assigned-clock-parents = <&k3_clks 125 2>; + }; + + main_rti1: watchdog@e010000 { +- compatible = "ti,j7-rti-wdt"; +- reg = <0x00 0xe010000 0x00 0x100>; +- clocks = <&k3_clks 126 0>; +- power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>; +- assigned-clocks = <&k3_clks 126 0>; +- assigned-clock-parents = <&k3_clks 126 2>; ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0xe010000 0x00 0x100>; ++ clocks = <&k3_clks 126 0>; ++ power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 126 0>; ++ assigned-clock-parents = <&k3_clks 126 2>; + }; + + icssg0: icssg@30000000 { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -146,6 +146,7 @@ + }; + + mcu_pmx0: pinctrl@4084000 { ++ bootph-all; + compatible = "pinctrl-single"; + reg = <0x00 0x4084000 0x00 0x84>; + #pinctrl-cells = <1>; +@@ -154,6 +155,7 @@ + }; + + mcu_esm: esm@4100000 { ++ bootph-pre-ram; + compatible = "ti,j721e-esm"; + reg = <0x00 0x4100000 0x00 0x1000>; + ti,esm-pins = <0>, <1>; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am64-phycore-som.dtsi 2024-03-28 11:26:09.893017428 -0400 +@@ -29,7 +29,7 @@ + reg = <0x00000000 0x80000000 0x00000000 0x80000000>; + }; + +- reserved-memory { ++ reserved_memory: reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; +@@ -39,6 +39,54 @@ + alignment = <0x1000>; + no-map; + }; ++ ++ main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core0_memory_region: r5f-memory@a0100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa1000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core1_memory_region: r5f-memory@a1100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa1100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a2000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa2000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core0_memory_region: r5f-memory@a2100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa2100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a3000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa3000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core1_memory_region: r5f-memory@a3100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa3100000 0x00 0xf00000>; ++ no-map; ++ }; + }; + + leds { +@@ -126,6 +174,12 @@ + AM64X_IOPAD(0x002c, PIN_OUTPUT, 0) /* (L19) OSPI0_CSn0 */ + >; + }; ++ ++ rtc_pins_default: rtc-defaults-pins { ++ pinctrl-single,pins = < ++ AM64X_IOPAD(0x0278, PIN_INPUT, 7) /* (C19) EXTINTn.GPIO1_70 */ ++ >; ++ }; + }; + + &cpsw3g { +@@ -160,6 +214,34 @@ + status = "disabled"; + }; + ++&mailbox0_cluster2 { ++ status = "okay"; ++ ++ mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 { ++ ti,mbox-rx = <0 0 2>; ++ ti,mbox-tx = <1 0 2>; ++ }; ++ ++ mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 { ++ ti,mbox-rx = <2 0 2>; ++ ti,mbox-tx = <3 0 2>; ++ }; ++}; ++ ++&mailbox0_cluster4 { ++ status = "okay"; ++ ++ mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 { ++ ti,mbox-rx = <0 0 2>; ++ ti,mbox-tx = <1 0 2>; ++ }; ++ ++ mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 { ++ ti,mbox-rx = <2 0 2>; ++ ti,mbox-tx = <3 0 2>; ++ }; ++}; ++ + &main_i2c0 { + status = "okay"; + pinctrl-names = "default"; +@@ -177,9 +259,38 @@ + i2c_som_rtc: rtc@52 { + compatible = "microcrystal,rv3028"; + reg = <0x52>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rtc_pins_default>; ++ interrupt-parent = <&main_gpio1>; ++ interrupts = <70 IRQ_TYPE_EDGE_FALLING>; ++ wakeup-source; + }; + }; + ++&main_r5fss0_core0 { ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core0>; ++ memory-region = <&main_r5fss0_core0_dma_memory_region>, ++ <&main_r5fss0_core0_memory_region>; ++}; ++ ++&main_r5fss0_core1 { ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss0_core1>; ++ memory-region = <&main_r5fss0_core1_dma_memory_region>, ++ <&main_r5fss0_core1_memory_region>; ++}; ++ ++&main_r5fss1_core0 { ++ mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core0>; ++ memory-region = <&main_r5fss1_core0_dma_memory_region>, ++ <&main_r5fss1_core0_memory_region>; ++}; ++ ++&main_r5fss1_core1 { ++ mboxes = <&mailbox0_cluster4 &mbox_main_r5fss1_core1>; ++ memory-region = <&main_r5fss1_core1_dma_memory_region>, ++ <&main_r5fss1_core1_memory_region>; ++}; ++ + &ospi0 { + status = "okay"; + pinctrl-names = "default"; +@@ -200,9 +311,17 @@ + }; + + &sdhci0 { ++ status = "okay"; + bus-width = <8>; + non-removable; + ti,driver-strength-ohm = <50>; + disable-wp; + keep-power-in-suspend; + }; ++ ++&tscadc0 { ++ status = "okay"; ++ adc { ++ ti,adc-channels = <0 1 2 3 4 5 6 7>; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -9,6 +9,7 @@ + * Common bits of the IOT2050 Basic variant, PG1 and PG2 + */ + ++#include "k3-am652.dtsi" + #include "k3-am65-iot2050-common.dtsi" + + / { +@@ -17,21 +18,6 @@ + /* 1G RAM */ + reg = <0x00000000 0x80000000 0x00000000 0x40000000>; + }; +- +- cpus { +- cpu-map { +- /delete-node/ cluster1; +- }; +- /delete-node/ cpu@100; +- /delete-node/ cpu@101; +- }; +- +- /delete-node/ l2-cache1; +-}; +- +-/* eMMC */ +-&sdhci0 { +- status = "disabled"; + }; + + &main_pmx0 { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am652.dtsi b/arch/arm64/boot/dts/ti/k3-am652.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am652.dtsi 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am652.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Device Tree Source for AM65 SoC family in Dual core configuration ++ * ++ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++#include "k3-am65.dtsi" ++ ++/ { ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cpu-map { ++ cluster0: cluster0 { ++ core0 { ++ cpu = <&cpu0>; ++ }; ++ ++ core1 { ++ cpu = <&cpu1>; ++ }; ++ }; ++ }; ++ ++ cpu0: cpu@0 { ++ compatible = "arm,cortex-a53"; ++ reg = <0x000>; ++ device_type = "cpu"; ++ enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <128>; ++ next-level-cache = <&L2_0>; ++ }; ++ ++ cpu1: cpu@1 { ++ compatible = "arm,cortex-a53"; ++ reg = <0x001>; ++ device_type = "cpu"; ++ enable-method = "psci"; ++ i-cache-size = <0x8000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; ++ d-cache-size = <0x8000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <128>; ++ next-level-cache = <&L2_0>; ++ }; ++ }; ++ ++ L2_0: l2-cache0 { ++ compatible = "cache"; ++ cache-level = <2>; ++ cache-unified; ++ cache-size = <0x80000>; ++ cache-line-size = <64>; ++ cache-sets = <512>; ++ next-level-cache = <&msmc_l3>; ++ }; ++ ++ msmc_l3: l3-cache0 { ++ compatible = "cache"; ++ cache-level = <3>; ++ cache-unified; ++ }; ++ ++ thermal_zones: thermal-zones { ++ #include "k3-am654-industrial-thermal.dtsi" ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -11,6 +11,7 @@ + + /dts-v1/; + ++#include "k3-am654.dtsi" + #include "k3-am65-iot2050-common.dtsi" + + / { +@@ -43,6 +44,7 @@ + + /* eMMC */ + &sdhci0 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc0_pins_default>; + bus-width = <8>; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2.dts b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2.dts +--- a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-m2.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -27,12 +27,6 @@ + }; + + &main_pmx0 { +- main_m2_enable_pins_default: main-m2-enable-default-pins { +- pinctrl-single,pins = < +- AM65X_IOPAD(0x01c4, PIN_INPUT_PULLUP, 7) /* (AH13) GPIO1_17 */ +- >; +- }; +- + main_bkey_pcie_reset: main-bkey-pcie-reset-default-pins { + pinctrl-single,pins = < + AM65X_IOPAD(0x01bc, PIN_OUTPUT_PULLUP, 7) /* (AG13) GPIO1_15 */ +@@ -66,15 +60,13 @@ + + &main_gpio0 { + pinctrl-names = "default"; +- pinctrl-0 = +- <&main_m2_pcie_mux_control>, +- <&arduino_io_d4_to_d9_pins_default>; ++ pinctrl-0 = <&main_m2_pcie_mux_control>; + }; + + &main_gpio1 { + pinctrl-names = "default"; + pinctrl-0 = +- <&main_m2_enable_pins_default>, ++ <&main_pcie_enable_pins_default>, + <&main_pmx0_m2_config_pins_default>, + <&main_pmx1_m2_config_pins_default>, + <&cp2102n_reset_pin_default>; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts +--- a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -369,6 +369,13 @@ + ti,enable-vout-discharge; + }; + ++ gpio@38 { ++ compatible = "nxp,pca9554"; ++ reg = <0x38>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++ + pca9554: gpio@39 { + compatible = "nxp,pca9554"; + reg = <0x39>; +@@ -442,6 +449,7 @@ + }; + + &sdhci0 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc0_pins_default>; + bus-width = <8>; +@@ -456,6 +464,7 @@ + * disable sdhci1 + */ + &sdhci1 { ++ status = "okay"; + vmmc-supply = <&vdd_mmc1_sd>; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; +@@ -522,13 +531,13 @@ + &mcu_r5fss0_core0 { + memory-region = <&mcu_r5fss0_core0_dma_memory_region>, + <&mcu_r5fss0_core0_memory_region>; +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + }; + + &mcu_r5fss0_core1 { + memory-region = <&mcu_r5fss0_core1_dma_memory_region>, + <&mcu_r5fss0_core1_memory_region>; +- mboxes = <&mailbox0_cluster1>, <&mbox_mcu_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster1 &mbox_mcu_r5fss0_core1>; + }; + + &ospi0 { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso b/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso +--- a/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am654-icssg2.dtso 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,145 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * DT overlay for IDK application board on AM654 EVM ++ * ++ * Copyright (C) 2018-2023 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include "k3-pinctrl.h" ++ ++&{/} { ++ aliases { ++ ethernet1 = "/icssg2-eth/ethernet-ports/port@0"; ++ ethernet2 = "/icssg2-eth/ethernet-ports/port@1"; ++ }; ++ ++ /* Ethernet node on PRU-ICSSG2 */ ++ icssg2_eth: icssg2-eth { ++ compatible = "ti,am654-icssg-prueth"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg2_rgmii_pins_default>; ++ sram = <&msmc_ram>; ++ ti,prus = <&pru2_0>, <&rtu2_0>, <&tx_pru2_0>, ++ <&pru2_1>, <&rtu2_1>, <&tx_pru2_1>; ++ firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf"; ++ ++ ti,pruss-gp-mux-sel = <2>, /* MII mode */ ++ <2>, ++ <2>, ++ <2>, /* MII mode */ ++ <2>, ++ <2>; ++ ++ ti,mii-g-rt = <&icssg2_mii_g_rt>; ++ ti,mii-rt = <&icssg2_mii_rt>; ++ ti,iep = <&icssg2_iep0>, <&icssg2_iep1>; ++ ++ interrupt-parent = <&icssg2_intc>; ++ interrupts = <24 0 2>, <25 1 3>; ++ interrupt-names = "tx_ts0", "tx_ts1"; ++ ++ dmas = <&main_udmap 0xc300>, /* egress slice 0 */ ++ <&main_udmap 0xc301>, /* egress slice 0 */ ++ <&main_udmap 0xc302>, /* egress slice 0 */ ++ <&main_udmap 0xc303>, /* egress slice 0 */ ++ <&main_udmap 0xc304>, /* egress slice 1 */ ++ <&main_udmap 0xc305>, /* egress slice 1 */ ++ <&main_udmap 0xc306>, /* egress slice 1 */ ++ <&main_udmap 0xc307>, /* egress slice 1 */ ++ <&main_udmap 0x4300>, /* ingress slice 0 */ ++ <&main_udmap 0x4301>; /* ingress slice 1 */ ++ ++ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", ++ "tx1-0", "tx1-1", "tx1-2", "tx1-3", ++ "rx0", "rx1"; ++ ethernet-ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ icssg2_emac0: port@0 { ++ reg = <0>; ++ phy-handle = <&icssg2_phy0>; ++ phy-mode = "rgmii-id"; ++ ti,syscon-rgmii-delay = <&scm_conf 0x4120>; ++ /* Filled in by bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++ icssg2_emac1: port@1 { ++ reg = <1>; ++ phy-handle = <&icssg2_phy1>; ++ phy-mode = "rgmii-id"; ++ ti,syscon-rgmii-delay = <&scm_conf 0x4124>; ++ /* Filled in by bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++ }; ++ }; ++}; ++ ++&main_pmx0 { ++ ++ icssg2_mdio_pins_default: icssg2-mdio-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x0094, PIN_INPUT, 2) /* (AC19) PRG2_PRU0_GPO7.PRG2_MDIO0_MDIO */ ++ AM65X_IOPAD(0x00c8, PIN_OUTPUT, 2) /* (AE15) PRG2_PRU1_GPO7.PRG2_MDIO0_MDC */ ++ >; ++ }; ++ ++ icssg2_rgmii_pins_default: icssg2-rgmii-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x00ac, PIN_INPUT, 2) /* (AH15) PRG2_PRU1_GPO0.PRG2_RGMII2_RD0 */ ++ AM65X_IOPAD(0x00b0, PIN_INPUT, 2) /* (AC16) PRG2_PRU1_GPO1.PRG2_RGMII2_RD1 */ ++ AM65X_IOPAD(0x00b4, PIN_INPUT, 2) /* (AD17) PRG2_PRU1_GPO2.PRG2_RGMII2_RD2 */ ++ AM65X_IOPAD(0x00b8, PIN_INPUT, 2) /* (AH14) PRG2_PRU1_GPO3.PRG2_RGMII2_RD3 */ ++ AM65X_IOPAD(0x00cc, PIN_OUTPUT, 2) /* (AD15) PRG2_PRU1_GPO8.PRG2_RGMII2_TD0 */ ++ AM65X_IOPAD(0x00d0, PIN_OUTPUT, 2) /* (AF14) PRG2_PRU1_GPO9.PRG2_RGMII2_TD1 */ ++ AM65X_IOPAD(0x00d4, PIN_OUTPUT, 2) /* (AC15) PRG2_PRU1_GPO10.PRG2_RGMII2_TD2 */ ++ AM65X_IOPAD(0x00d8, PIN_OUTPUT, 2) /* (AD14) PRG2_PRU1_GPO11.PRG2_RGMII2_TD3 */ ++ AM65X_IOPAD(0x00dc, PIN_INPUT, 2) /* (AE14) PRG2_PRU1_GPO16.PRG2_RGMII2_TXC */ ++ AM65X_IOPAD(0x00c4, PIN_OUTPUT, 2) /* (AC17) PRG2_PRU1_GPO6.PRG2_RGMII2_TX_CTL */ ++ AM65X_IOPAD(0x00c0, PIN_INPUT, 2) /* (AG15) PRG2_PRU1_GPO5.PRG2_RGMII2_RXC */ ++ AM65X_IOPAD(0x00bc, PIN_INPUT, 2) /* (AG14) PRG2_PRU1_GPO4.PRG2_RGMII2_RX_CTL */ ++ ++ AM65X_IOPAD(0x0078, PIN_INPUT, 2) /* (AF18) PRG2_PRU0_GPO0.PRG2_RGMII1_RD0 */ ++ AM65X_IOPAD(0x007c, PIN_INPUT, 2) /* (AE18) PRG2_PRU0_GPO1.PRG2_RGMII1_RD1 */ ++ AM65X_IOPAD(0x0080, PIN_INPUT, 2) /* (AH17) PRG2_PRU0_GPO2.PRG2_RGMII1_RD2 */ ++ AM65X_IOPAD(0x0084, PIN_INPUT, 2) /* (AG18) PRG2_PRU0_GPO3.PRG2_RGMII1_RD3 */ ++ AM65X_IOPAD(0x0098, PIN_OUTPUT, 2) /* (AH16) PRG2_PRU0_GPO8.PRG2_RGMII1_TD0 */ ++ AM65X_IOPAD(0x009c, PIN_OUTPUT, 2) /* (AG16) PRG2_PRU0_GPO9.PRG2_RGMII1_TD1 */ ++ AM65X_IOPAD(0x00a0, PIN_OUTPUT, 2) /* (AF16) PRG2_PRU0_GPO10.PRG2_RGMII1_TD2 */ ++ AM65X_IOPAD(0x00a4, PIN_OUTPUT, 2) /* (AE16) PRG2_PRU0_GPO11.PRG2_RGMII1_TD3 */ ++ AM65X_IOPAD(0x00a8, PIN_INPUT, 2) /* (AD16) PRG2_PRU0_GPO16.PRG2_RGMII1_TXC */ ++ AM65X_IOPAD(0x0090, PIN_OUTPUT, 2) /* (AE17) PRG2_PRU0_GPO6.PRG2_RGMII1_TX_CTL */ ++ AM65X_IOPAD(0x008c, PIN_INPUT, 2) /* (AF17) PRG2_PRU0_GPO5.PRG2_RGMII1_RXC */ ++ AM65X_IOPAD(0x0088, PIN_INPUT, 2) /* (AG17) PRG2_PRU0_GPO4.PRG2_RGMII1_RX_CTL */ ++ >; ++ }; ++}; ++ ++&icssg2_mdio { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg2_mdio_pins_default>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ icssg2_phy0: ethernet-phy@0 { ++ reg = <0>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ }; ++ ++ icssg2_phy1: ethernet-phy@3 { ++ reg = <3>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso +--- a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,296 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * DT overlay for IDK application board on AM654 EVM ++ * ++ * Copyright (C) 2018-2023 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include "k3-pinctrl.h" ++ ++&{/} { ++ aliases { ++ ethernet3 = "/icssg0-eth/ethernet-ports/port@0"; ++ ethernet4 = "/icssg0-eth/ethernet-ports/port@1"; ++ ethernet5 = "/icssg1-eth/ethernet-ports/port@0"; ++ ethernet6 = "/icssg1-eth/ethernet-ports/port@1"; ++ }; ++ ++ /* Ethernet node on PRU-ICSSG0 */ ++ icssg0_eth: icssg0-eth { ++ compatible = "ti,am654-icssg-prueth"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg0_rgmii_pins_default>; ++ sram = <&msmc_ram>; ++ ti,prus = <&pru0_0>, <&rtu0_0>, <&tx_pru0_0>, <&pru0_1>, <&rtu0_1>, <&tx_pru0_1>; ++ firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf"; ++ ++ ti,pruss-gp-mux-sel = <2>, /* MII mode */ ++ <2>, ++ <2>, ++ <2>, /* MII mode */ ++ <2>, ++ <2>; ++ ++ ti,mii-g-rt = <&icssg0_mii_g_rt>; ++ ti,mii-rt = <&icssg0_mii_rt>; ++ ti,iep = <&icssg0_iep0>, <&icssg0_iep1>; ++ ++ interrupt-parent = <&icssg0_intc>; ++ interrupts = <24 0 2>, <25 1 3>; ++ interrupt-names = "tx_ts0", "tx_ts1"; ++ ++ dmas = <&main_udmap 0xc100>, /* egress slice 0 */ ++ <&main_udmap 0xc101>, /* egress slice 0 */ ++ <&main_udmap 0xc102>, /* egress slice 0 */ ++ <&main_udmap 0xc103>, /* egress slice 0 */ ++ <&main_udmap 0xc104>, /* egress slice 1 */ ++ <&main_udmap 0xc105>, /* egress slice 1 */ ++ <&main_udmap 0xc106>, /* egress slice 1 */ ++ <&main_udmap 0xc107>, /* egress slice 1 */ ++ ++ <&main_udmap 0x4100>, /* ingress slice 0 */ ++ <&main_udmap 0x4101>, /* ingress slice 1 */ ++ <&main_udmap 0x4102>, /* mgmnt rsp slice 0 */ ++ <&main_udmap 0x4103>; /* mgmnt rsp slice 1 */ ++ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", ++ "tx1-0", "tx1-1", "tx1-2", "tx1-3", ++ "rx0", "rx1"; ++ ++ ethernet-ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ icssg0_emac0: port@0 { ++ reg = <0>; ++ phy-handle = <&icssg0_phy0>; ++ phy-mode = "rgmii-id"; ++ ti,syscon-rgmii-delay = <&scm_conf 0x4100>; ++ /* Filled in by bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++ icssg0_emac1: port@1 { ++ reg = <1>; ++ phy-handle = <&icssg0_phy1>; ++ phy-mode = "rgmii-id"; ++ ti,syscon-rgmii-delay = <&scm_conf 0x4104>; ++ /* Filled in by bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++ }; ++ }; ++ ++ /* Ethernet node on PRU-ICSSG1 */ ++ icssg1_eth: icssg1-eth { ++ compatible = "ti,am654-icssg-prueth"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg1_rgmii_pins_default>; ++ sram = <&msmc_ram>; ++ ti,prus = <&pru1_0>, <&rtu1_0>, <&tx_pru1_0>, <&pru1_1>, <&rtu1_1>, <&tx_pru1_1>; ++ firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf"; ++ ++ ti,pruss-gp-mux-sel = <2>, /* MII mode */ ++ <2>, ++ <2>, ++ <2>, /* MII mode */ ++ <2>, ++ <2>; ++ ++ ti,mii-g-rt = <&icssg1_mii_g_rt>; ++ ti,mii-rt = <&icssg1_mii_rt>; ++ ti,iep = <&icssg1_iep0>, <&icssg1_iep1>; ++ ++ interrupt-parent = <&icssg1_intc>; ++ interrupts = <24 0 2>, <25 1 3>; ++ interrupt-names = "tx_ts0", "tx_ts1"; ++ ++ dmas = <&main_udmap 0xc200>, /* egress slice 0 */ ++ <&main_udmap 0xc201>, /* egress slice 0 */ ++ <&main_udmap 0xc202>, /* egress slice 0 */ ++ <&main_udmap 0xc203>, /* egress slice 0 */ ++ <&main_udmap 0xc204>, /* egress slice 1 */ ++ <&main_udmap 0xc205>, /* egress slice 1 */ ++ <&main_udmap 0xc206>, /* egress slice 1 */ ++ <&main_udmap 0xc207>, /* egress slice 1 */ ++ ++ <&main_udmap 0x4200>, /* ingress slice 0 */ ++ <&main_udmap 0x4201>, /* ingress slice 1 */ ++ <&main_udmap 0x4202>, /* mgmnt rsp slice 0 */ ++ <&main_udmap 0x4203>; /* mgmnt rsp slice 1 */ ++ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", ++ "tx1-0", "tx1-1", "tx1-2", "tx1-3", ++ "rx0", "rx1"; ++ ++ ethernet-ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ icssg1_emac0: port@0 { ++ reg = <0>; ++ phy-handle = <&icssg1_phy0>; ++ phy-mode = "rgmii-id"; ++ ti,syscon-rgmii-delay = <&scm_conf 0x4110>; ++ /* Filled in by bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++ icssg1_emac1: port@1 { ++ reg = <1>; ++ phy-handle = <&icssg1_phy1>; ++ phy-mode = "rgmii-id"; ++ ti,syscon-rgmii-delay = <&scm_conf 0x4114>; ++ /* Filled in by bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++ }; ++ }; ++}; ++ ++&main_pmx0 { ++ ++ icssg0_mdio_pins_default: icssg0-mdio-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x0294, PIN_INPUT, 0) /* (AE26) PRG0_MDIO0_MDIO */ ++ AM65X_IOPAD(0x0298, PIN_OUTPUT, 0) /* (AE28) PRG0_MDIO0_MDC */ ++ >; ++ }; ++ ++ icssg0_rgmii_pins_default: icssg0-rgmii-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x0244, PIN_INPUT, 2) /* (AB28) PRG0_PRU1_GPO0.PRG0_RGMII2_RD0 */ ++ AM65X_IOPAD(0x0248, PIN_INPUT, 2) /* (AC28) PRG0_PRU1_GPO1.PRG0_RGMII2_RD1 */ ++ AM65X_IOPAD(0x024c, PIN_INPUT, 2) /* (AC27) PRG0_PRU1_GPO2.PRG0_RGMII2_RD2 */ ++ AM65X_IOPAD(0x0250, PIN_INPUT, 2) /* (AB26) PRG0_PRU1_GPO3.PRG0_RGMII2_RD3 */ ++ AM65X_IOPAD(0x0274, PIN_OUTPUT, 2) /* (AC25) PRG0_PRU1_GPO12.PRG0_RGMII2_TD0 */ ++ AM65X_IOPAD(0x0278, PIN_OUTPUT, 2) /* (AD25) PRG0_PRU1_GPO13.PRG0_RGMII2_TD1 */ ++ AM65X_IOPAD(0x027c, PIN_OUTPUT, 2) /* (AD24) PRG0_PRU1_GPO14.PRG0_RGMII2_TD2 */ ++ AM65X_IOPAD(0x0280, PIN_OUTPUT, 2) /* (AE27) PRG0_PRU1_GPO15.PRG0_RGMII2_TD3 */ ++ AM65X_IOPAD(0x0284, PIN_INPUT, 2) /* (AC24) PRG0_PRU1_GPO16.PRG0_RGMII2_TXC */ ++ AM65X_IOPAD(0x0270, PIN_OUTPUT, 2) /* (AB24) PRG0_PRU1_GPO11.PRG0_RGMII2_TX_CTL */ ++ AM65X_IOPAD(0x025c, PIN_INPUT, 2) /* (AB27) PRG0_PRU1_GPO6.PRG0_RGMII2_RXC */ ++ AM65X_IOPAD(0x0254, PIN_INPUT, 2) /* (AA25) PRG0_PRU1_GPO4.PRG0_RGMII2_RX_CTL */ ++ ++ AM65X_IOPAD(0x01f4, PIN_INPUT, 2) /* (V24) PRG0_PRU0_GPO0.PRG0_RGMII1_RD0 */ ++ AM65X_IOPAD(0x01f8, PIN_INPUT, 2) /* (W25) PRG0_PRU0_GPO1.PRG0_RGMII1_RD1 */ ++ AM65X_IOPAD(0x01fc, PIN_INPUT, 2) /* (W24) PRG0_PRU0_GPO2.PRG0_RGMII1_RD2 */ ++ AM65X_IOPAD(0x0200, PIN_INPUT, 2) /* (AA27) PRG0_PRU0_GPO3.PRG0_RGMII1_RD3 */ ++ AM65X_IOPAD(0x0224, PIN_OUTPUT, 2) /* (AD27) PRG0_PRU0_GPO12.PRG0_RGMII1_TD0 */ ++ AM65X_IOPAD(0x0228, PIN_OUTPUT, 2) /* (AC26) PRG0_PRU0_GPO13.PRG0_RGMII1_TD1 */ ++ AM65X_IOPAD(0x022c, PIN_OUTPUT, 2) /* (AD26) PRG0_PRU0_GPO14.PRG0_RGMII1_TD2 */ ++ AM65X_IOPAD(0x0230, PIN_OUTPUT, 2) /* (AA24) PRG0_PRU0_GPO15.PRG0_RGMII1_TD3 */ ++ AM65X_IOPAD(0x0234, PIN_INPUT, 2) /* (AD28) PRG0_PRU0_GPO16.PRG0_RGMII1_TXC */ ++ AM65X_IOPAD(0x0220, PIN_OUTPUT, 2) /* (AB25) PRG0_PRU0_GPO11.PRG0_RGMII1_TX_CTL */ ++ AM65X_IOPAD(0x020c, PIN_INPUT, 2) /* (Y25) PRG0_PRU0_GPO6.PRG0_RGMII1_RXC */ ++ AM65X_IOPAD(0x0204, PIN_INPUT, 2) /* (Y24) PRG0_PRU0_GPO4.PRG0_RGMII1_RX_CTL */ ++ >; ++ }; ++ ++ icssg0_iep0_pins_default: icssg0-iep0-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x0240, PIN_INPUT, 2) /* (U24) PRG0_PRU0_GPO19.PRG0_IEP0_EDC_SYNC_OUT0 */ ++ >; ++ }; ++ ++ icssg1_mdio_pins_default: icssg1-mdio-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x0180, PIN_INPUT, 0) /* (AD18) PRG1_MDIO0_MDIO */ ++ AM65X_IOPAD(0x0184, PIN_OUTPUT, 0) /* (AH18) PRG1_MDIO0_MDC */ ++ >; ++ }; ++ ++ icssg1_rgmii_pins_default: icssg1-rgmii-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x0130, PIN_INPUT, 2) /* (AH24) PRG1_PRU1_GPO0.PRG1_RGMII2_RD0 */ ++ AM65X_IOPAD(0x0134, PIN_INPUT, 2) /* (AH23) PRG1_PRU1_GPO1.PRG1_RGMII2_RD1 */ ++ AM65X_IOPAD(0x0138, PIN_INPUT, 2) /* (AG21) PRG1_PRU1_GPO2.PRG1_RGMII2_RD2 */ ++ AM65X_IOPAD(0x013c, PIN_INPUT, 2) /* (AH22) PRG1_PRU1_GPO3.PRG1_RGMII2_RD3 */ ++ AM65X_IOPAD(0x0160, PIN_OUTPUT, 2) /* (AE20) PRG1_PRU1_GPO12.PRG1_RGMII2_TD0 */ ++ AM65X_IOPAD(0x0164, PIN_OUTPUT, 2) /* (AF19) PRG1_PRU1_GPO13.PRG1_RGMII2_TD1 */ ++ AM65X_IOPAD(0x0168, PIN_OUTPUT, 2) /* (AH19) PRG1_PRU1_GPO14.PRG1_RGMII2_TD2 */ ++ AM65X_IOPAD(0x016c, PIN_OUTPUT, 2) /* (AG19) PRG1_PRU1_GPO15.PRG1_RGMII2_TD3 */ ++ AM65X_IOPAD(0x0170, PIN_INPUT, 2) /* (AE19) PRG1_PRU1_GPO16.PRG1_RGMII2_TXC */ ++ AM65X_IOPAD(0x015c, PIN_OUTPUT, 2) /* (AC20) PRG1_PRU1_GPO11.PRG1_RGMII2_TX_CTL */ ++ AM65X_IOPAD(0x0148, PIN_INPUT, 2) /* (AG22) PRG1_PRU1_GPO6.PRG1_RGMII2_RXC */ ++ AM65X_IOPAD(0x0140, PIN_INPUT, 2) /* (AE21) PRG1_PRU1_GPO4.PRG1_RGMII2_RX_CTL */ ++ ++ AM65X_IOPAD(0x00e0, PIN_INPUT, 2) /* (AE22) PRG1_PRU0_GPO0.PRG1_RGMII1_RD0 */ ++ AM65X_IOPAD(0x00e4, PIN_INPUT, 2) /* (AG24) PRG1_PRU0_GPO1.PRG1_RGMII1_RD1 */ ++ AM65X_IOPAD(0x00e8, PIN_INPUT, 2) /* (AF23) PRG1_PRU0_GPO2.PRG1_RGMII1_RD2 */ ++ AM65X_IOPAD(0x00ec, PIN_INPUT, 2) /* (AD21) PRG1_PRU0_GPO3.PRG1_RGMII1_RD3 */ ++ AM65X_IOPAD(0x0110, PIN_OUTPUT, 2) /* (AH20) PRG1_PRU0_GPO12.PRG1_RGMII1_TD0 */ ++ AM65X_IOPAD(0x0114, PIN_OUTPUT, 2) /* (AH21) PRG1_PRU0_GPO13.PRG1_RGMII1_TD1 */ ++ AM65X_IOPAD(0x0118, PIN_OUTPUT, 2) /* (AG20) PRG1_PRU0_GPO14.PRG1_RGMII1_TD2 */ ++ AM65X_IOPAD(0x011c, PIN_OUTPUT, 2) /* (AD19) PRG1_PRU0_GPO15.PRG1_RGMII1_TD3 */ ++ AM65X_IOPAD(0x0120, PIN_INPUT, 2) /* (AD20) PRG1_PRU0_GPO16.PRG1_RGMII1_TXC */ ++ AM65X_IOPAD(0x010c, PIN_OUTPUT, 2) /* (AF21) PRG1_PRU0_GPO11.PRG1_RGMII1_TX_CTL */ ++ AM65X_IOPAD(0x00f8, PIN_INPUT, 2) /* (AF22) PRG1_PRU0_GPO6.PRG1_RGMII1_RXC */ ++ AM65X_IOPAD(0x00f0, PIN_INPUT, 2) /* (AG23) PRG1_PRU0_GPO4.PRG1_RGMII1_RX_CTL */ ++ >; ++ }; ++ ++ icssg1_iep0_pins_default: icssg1-iep0-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x012c, PIN_INPUT, 2) /* (AG26) PRG1_PRU0_GPO19.PRG1_IEP0_EDC_SYNC_OUT0 */ ++ >; ++ }; ++}; ++ ++&icssg0_mdio { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg0_mdio_pins_default>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ icssg0_phy0: ethernet-phy@0 { ++ reg = <0>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ }; ++ ++ icssg0_phy1: ethernet-phy@3 { ++ reg = <3>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ }; ++}; ++ ++&icssg0_iep0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg0_iep0_pins_default>; ++}; ++ ++&icssg1_mdio { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg1_mdio_pins_default>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ icssg1_phy0: ethernet-phy@0 { ++ reg = <0>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ }; ++ ++ icssg1_phy1: ethernet-phy@3 { ++ reg = <3>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ }; ++}; ++ ++&icssg1_iep0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg1_iep0_pins_default>; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-pcie-usb2.dtso b/arch/arm64/boot/dts/ti/k3-am654-pcie-usb2.dtso +--- a/arch/arm64/boot/dts/ti/k3-am654-pcie-usb2.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am654-pcie-usb2.dtso 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,59 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/** ++ * DT overlay for SERDES personality card: 2lane PCIe + USB2.0 Host on AM654 EVM ++ * ++ * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++#include ++#include ++#include ++#include "k3-pinctrl.h" ++ ++&serdes0 { ++ assigned-clocks = <&k3_clks 153 4>, ++ <&serdes0 AM654_SERDES_CMU_REFCLK>, ++ <&serdes0 AM654_SERDES_RO_REFCLK>; ++ assigned-clock-parents = <&k3_clks 153 8>, ++ <&k3_clks 153 4>, ++ <&k3_clks 153 4>; ++ status = "okay"; ++}; ++ ++&serdes1 { ++ assigned-clocks = <&serdes1 AM654_SERDES_CMU_REFCLK>; ++ assigned-clock-parents = <&serdes0 AM654_SERDES_RO_REFCLK>; ++ status = "okay"; ++}; ++ ++&pcie0_rc { ++ num-lanes = <2>; ++ phys = <&serdes0 PHY_TYPE_PCIE 1>, <&serdes1 PHY_TYPE_PCIE 1>; ++ phy-names = "pcie-phy0", "pcie-phy1"; ++ reset-gpios = <&pca9555 5 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++}; ++ ++&main_pmx0 { ++ usb0_pins_default: usb0-pins-default { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x02bc, PIN_OUTPUT, 0) /* (AD9) USB0_DRVVBUS */ ++ >; ++ }; ++}; ++ ++&dwc3_0 { ++ status = "okay"; ++}; ++ ++&usb0_phy { ++ status = "okay"; ++}; ++ ++&usb0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb0_pins_default>; ++ dr_mode = "host"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-pcie-usb3.dtso b/arch/arm64/boot/dts/ti/k3-am654-pcie-usb3.dtso +--- a/arch/arm64/boot/dts/ti/k3-am654-pcie-usb3.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am654-pcie-usb3.dtso 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,61 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/** ++ * DT overlay for SERDES personality card: 1lane PCIe + USB3.0 DRD on AM654 EVM ++ * ++ * Copyright (C) 2018-2024 Texas Instruments Incorporated - http://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++#include ++#include ++#include ++ ++#include "k3-pinctrl.h" ++ ++&serdes1 { ++ status = "okay"; ++}; ++ ++&pcie1_rc { ++ num-lanes = <1>; ++ phys = <&serdes1 PHY_TYPE_PCIE 0>; ++ phy-names = "pcie-phy0"; ++ reset-gpios = <&pca9555 5 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++}; ++ ++&main_pmx0 { ++ usb0_pins_default: usb0_pins_default { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x02bc, PIN_OUTPUT, 0) /* (AD9) USB0_DRVVBUS */ ++ >; ++ }; ++}; ++ ++&serdes0 { ++ status = "okay"; ++ assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>; ++ assigned-clock-parents = <&k3_clks 153 7>, <&k3_clks 153 4>; ++}; ++ ++&dwc3_0 { ++ status = "okay"; ++ assigned-clock-parents = <&k3_clks 151 4>, /* set REF_CLK to 20MHz i.e. PER0_PLL/48 */ ++ <&k3_clks 151 8>; /* set PIPE3_TXB_CLK to WIZ8B2M4VSB */ ++ phys = <&serdes0 PHY_TYPE_USB3 0>; ++ phy-names = "usb3-phy"; ++}; ++ ++&usb0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&usb0_pins_default>; ++ dr_mode = "host"; ++ maximum-speed = "super-speed"; ++ snps,dis-u1-entry-quirk; ++ snps,dis-u2-entry-quirk; ++}; ++ ++&usb0_phy { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -9,8 +9,8 @@ + * Common bits of the IOT2050 Basic and Advanced variants, PG1 and PG2 + */ + +-#include "k3-am654.dtsi" + #include ++#include + + / { + aliases { +@@ -27,6 +27,8 @@ + spi0 = &mcu_spi0; + mmc0 = &sdhci1; + mmc1 = &sdhci0; ++ ethernet1 = &icssg0_emac0; ++ ethernet2 = &icssg0_emac1; + }; + + chosen { +@@ -73,6 +75,12 @@ + alignment = <0x1000>; + no-map; + }; ++ ++ /* To reserve the power-on(PON) reason for watchdog reset */ ++ wdt_reset_memory_region: wdt-memory@a2200000 { ++ reg = <0x00 0xa2200000 0x00 0x1000>; ++ no-map; ++ }; + }; + + leds { +@@ -111,9 +119,498 @@ + #clock-cells = <0>; + clock-frequency = <19200000>; + }; ++ ++ /* Dual Ethernet application node on PRU-ICSSG0 */ ++ icssg0_eth: icssg0-eth { ++ compatible = "ti,am654-icssg-prueth"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg0_rgmii_pins_default>; ++ sram = <&msmc_ram>; ++ ++ ti,prus = <&pru0_0>, <&rtu0_0>, <&tx_pru0_0>, ++ <&pru0_1>, <&rtu0_1>, <&tx_pru0_1>; ++ firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", ++ "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf"; ++ ++ ti,pruss-gp-mux-sel = <2>, /* MII mode */ ++ <2>, ++ <2>, ++ <2>, /* MII mode */ ++ <2>, ++ <2>; ++ ++ ti,mii-g-rt = <&icssg0_mii_g_rt>; ++ ti,mii-rt = <&icssg0_mii_rt>; ++ ti,iep = <&icssg0_iep0>, <&icssg0_iep1>; ++ ++ interrupt-parent = <&icssg0_intc>; ++ interrupts = <24 0 2>, <25 1 3>; ++ interrupt-names = "tx_ts0", "tx_ts1"; ++ ++ dmas = <&main_udmap 0xc100>, /* egress slice 0 */ ++ <&main_udmap 0xc101>, /* egress slice 0 */ ++ <&main_udmap 0xc102>, /* egress slice 0 */ ++ <&main_udmap 0xc103>, /* egress slice 0 */ ++ <&main_udmap 0xc104>, /* egress slice 1 */ ++ <&main_udmap 0xc105>, /* egress slice 1 */ ++ <&main_udmap 0xc106>, /* egress slice 1 */ ++ <&main_udmap 0xc107>, /* egress slice 1 */ ++ <&main_udmap 0x4100>, /* ingress slice 0 */ ++ <&main_udmap 0x4101>; /* ingress slice 1 */ ++ dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3", ++ "tx1-0", "tx1-1", "tx1-2", "tx1-3", ++ "rx0", "rx1"; ++ ++ ethernet-ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ icssg0_emac0: port@0 { ++ reg = <0>; ++ phy-handle = <&icssg0_eth0_phy>; ++ phy-mode = "rgmii-id"; ++ ti,syscon-rgmii-delay = <&scm_conf 0x4100>; ++ ti,half-duplex-capable; ++ /* Filled in by bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++ ++ icssg0_emac1: port@1 { ++ reg = <1>; ++ phy-handle = <&icssg0_eth1_phy>; ++ phy-mode = "rgmii-id"; ++ ti,syscon-rgmii-delay = <&scm_conf 0x4104>; ++ ti,half-duplex-capable; ++ /* Filled in by bootloader */ ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++ }; ++ }; + }; + + &wkup_pmx0 { ++ pinctrl-names = ++ "default", ++ "d0-uart0-rxd", "d0-gpio", "d0-gpio-pullup", "d0-gpio-pulldown", ++ "d1-uart0-txd", "d1-gpio", "d1-gpio-pullup", "d1-gpio-pulldown", ++ "d2-uart0-ctsn", "d2-gpio", "d2-gpio-pullup", "d2-gpio-pulldown", ++ "d3-uart0-rtsn", "d3-gpio", "d3-gpio-pullup", "d3-gpio-pulldown", ++ "d10-spi0-cs0", "d10-gpio", "d10-gpio-pullup", "d10-gpio-pulldown", ++ "d11-spi0-d0", "d11-gpio", "d11-gpio-pullup", "d11-gpio-pulldown", ++ "d12-spi0-d1", "d12-gpio", "d12-gpio-pullup", "d12-gpio-pulldown", ++ "d13-spi0-clk", "d13-gpio", "d13-gpio-pullup", "d13-gpio-pulldown", ++ "a0-gpio", "a0-gpio-pullup", "a0-gpio-pulldown", ++ "a1-gpio", "a1-gpio-pullup", "a1-gpio-pulldown", ++ "a2-gpio", "a2-gpio-pullup", "a2-gpio-pulldown", ++ "a3-gpio", "a3-gpio-pullup", "a3-gpio-pulldown", ++ "a4-gpio", "a4-gpio-pullup", "a4-gpio-pulldown", ++ "a5-gpio", "a5-gpio-pullup", "a5-gpio-pulldown"; ++ ++ pinctrl-0 = <&d0_uart0_rxd>; ++ pinctrl-1 = <&d0_uart0_rxd>; ++ pinctrl-2 = <&d0_gpio>; ++ pinctrl-3 = <&d0_gpio_pullup>; ++ pinctrl-4 = <&d0_gpio_pulldown>; ++ pinctrl-5 = <&d1_uart0_txd>; ++ pinctrl-6 = <&d1_gpio>; ++ pinctrl-7 = <&d1_gpio_pullup>; ++ pinctrl-8 = <&d1_gpio_pulldown>; ++ pinctrl-9 = <&d2_uart0_ctsn>; ++ pinctrl-10 = <&d2_gpio>; ++ pinctrl-11 = <&d2_gpio_pullup>; ++ pinctrl-12 = <&d2_gpio_pulldown>; ++ pinctrl-13 = <&d3_uart0_rtsn>; ++ pinctrl-14 = <&d3_gpio>; ++ pinctrl-15 = <&d3_gpio_pullup>; ++ pinctrl-16 = <&d3_gpio_pulldown>; ++ pinctrl-17 = <&d10_spi0_cs0>; ++ pinctrl-18 = <&d10_gpio>; ++ pinctrl-19 = <&d10_gpio_pullup>; ++ pinctrl-20 = <&d10_gpio_pulldown>; ++ pinctrl-21 = <&d11_spi0_d0>; ++ pinctrl-22 = <&d11_gpio>; ++ pinctrl-23 = <&d11_gpio_pullup>; ++ pinctrl-24 = <&d11_gpio_pulldown>; ++ pinctrl-25 = <&d12_spi0_d1>; ++ pinctrl-26 = <&d12_gpio>; ++ pinctrl-27 = <&d12_gpio_pullup>; ++ pinctrl-28 = <&d12_gpio_pulldown>; ++ pinctrl-29 = <&d13_spi0_clk>; ++ pinctrl-30 = <&d13_gpio>; ++ pinctrl-31 = <&d13_gpio_pullup>; ++ pinctrl-32 = <&d13_gpio_pulldown>; ++ pinctrl-33 = <&a0_gpio>; ++ pinctrl-34 = <&a0_gpio_pullup>; ++ pinctrl-35 = <&a0_gpio_pulldown>; ++ pinctrl-36 = <&a1_gpio>; ++ pinctrl-37 = <&a1_gpio_pullup>; ++ pinctrl-38 = <&a1_gpio_pulldown>; ++ pinctrl-39 = <&a2_gpio>; ++ pinctrl-40 = <&a2_gpio_pullup>; ++ pinctrl-41 = <&a2_gpio_pulldown>; ++ pinctrl-42 = <&a3_gpio>; ++ pinctrl-43 = <&a3_gpio_pullup>; ++ pinctrl-44 = <&a3_gpio_pulldown>; ++ pinctrl-45 = <&a4_gpio>; ++ pinctrl-46 = <&a4_gpio_pullup>; ++ pinctrl-47 = <&a4_gpio_pulldown>; ++ pinctrl-48 = <&a5_gpio>; ++ pinctrl-49 = <&a5_gpio_pullup>; ++ pinctrl-50 = <&a5_gpio_pulldown>; ++ ++ d0_uart0_rxd: d0-uart0-rxd-pins { ++ pinctrl-single,pins = < ++ /* (P4) MCU_UART0_RXD */ ++ AM65X_WKUP_IOPAD(0x0044, PIN_INPUT, 4) ++ >; ++ }; ++ ++ d0_gpio: d0-gpio-pins { ++ pinctrl-single,pins = < ++ /* (P4) WKUP_GPIO0_29 */ ++ AM65X_WKUP_IOPAD(0x0044, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d0_gpio_pullup: d0-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (P4) WKUP_GPIO0_29 */ ++ AM65X_WKUP_IOPAD(0x0044, PIN_INPUT_PULLUP, 7) ++ >; ++ }; ++ ++ d0_gpio_pulldown: d0-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (P4) WKUP_GPIO0_29 */ ++ AM65X_WKUP_IOPAD(0x0044, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d1_uart0_txd: d1-uart0-txd-pins { ++ pinctrl-single,pins = < ++ /* (P5) MCU_UART0_TXD */ ++ AM65X_WKUP_IOPAD(0x0048, PIN_OUTPUT, 4) ++ >; ++ }; ++ ++ d1_gpio: d1-gpio-pins { ++ pinctrl-single,pins = < ++ /* (P5) WKUP_GPIO0_30 */ ++ AM65X_WKUP_IOPAD(0x0048, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d1_gpio_pullup: d1-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (P5) WKUP_GPIO0_30 */ ++ AM65X_WKUP_IOPAD(0x0048, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d1_gpio_pulldown: d1-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (P5) WKUP_GPIO0_30 */ ++ AM65X_WKUP_IOPAD(0x0048, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d2_uart0_ctsn: d2-uart0-ctsn-pins { ++ pinctrl-single,pins = < ++ /* (P1) MCU_UART0_CTSn */ ++ AM65X_WKUP_IOPAD(0x004C, PIN_INPUT, 4) ++ >; ++ }; ++ ++ d2_gpio: d2-gpio-pins { ++ pinctrl-single,pins = < ++ /* (P5) WKUP_GPIO0_31 */ ++ AM65X_WKUP_IOPAD(0x004C, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d2_gpio_pullup: d2-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (P5) WKUP_GPIO0_31 */ ++ AM65X_WKUP_IOPAD(0x004C, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d2_gpio_pulldown: d2-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (P5) WKUP_GPIO0_31 */ ++ AM65X_WKUP_IOPAD(0x004C, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d3_uart0_rtsn: d3-uart0-rtsn-pins { ++ pinctrl-single,pins = < ++ /* (N3) MCU_UART0_RTSn */ ++ AM65X_WKUP_IOPAD(0x0054, PIN_OUTPUT, 4) ++ >; ++ }; ++ ++ d3_gpio: d3-gpio-pins { ++ pinctrl-single,pins = < ++ /* (N3) WKUP_GPIO0_33 */ ++ AM65X_WKUP_IOPAD(0x0054, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d3_gpio_pullup: d3-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (N3) WKUP_GPIO0_33 */ ++ AM65X_WKUP_IOPAD(0x0054, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d3_gpio_pulldown: d3-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (N3) WKUP_GPIO0_33 */ ++ AM65X_WKUP_IOPAD(0x0054, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d10_spi0_cs0: d10-spi0-cs0-pins { ++ pinctrl-single,pins = < ++ /* (Y4) MCU_SPI0_CS0 */ ++ AM65X_WKUP_IOPAD(0x009c, PIN_OUTPUT, 0) ++ >; ++ }; ++ ++ d10_gpio: d10-gpio-pins { ++ pinctrl-single,pins = < ++ /* (Y4) WKUP_GPIO0_51 */ ++ AM65X_WKUP_IOPAD(0x009c, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d10_gpio_pullup: d10-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (Y4) WKUP_GPIO0_51 */ ++ AM65X_WKUP_IOPAD(0x009c, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d10_gpio_pulldown: d10-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (Y4) WKUP_GPIO0_51 */ ++ AM65X_WKUP_IOPAD(0x009c, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d11_spi0_d0: d11-spi0-d0-pins { ++ pinctrl-single,pins = < ++ /* (Y3) MCU_SPI0_D0 */ ++ AM65X_WKUP_IOPAD(0x0094, PIN_INPUT, 0) ++ >; ++ }; ++ ++ d11_gpio: d11-gpio-pins { ++ pinctrl-single,pins = < ++ /* (Y3) WKUP_GPIO0_49 */ ++ AM65X_WKUP_IOPAD(0x0094, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d11_gpio_pullup: d11-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (Y3) WKUP_GPIO0_49 */ ++ AM65X_WKUP_IOPAD(0x0094, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d11_gpio_pulldown: d11-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (Y3) WKUP_GPIO0_49 */ ++ AM65X_WKUP_IOPAD(0x0094, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d12_spi0_d1: d12-spi0-d1-pins { ++ pinctrl-single,pins = < ++ /* (Y2) MCU_SPI0_D1 */ ++ AM65X_WKUP_IOPAD(0x0098, PIN_INPUT, 0) ++ >; ++ }; ++ ++ d12_gpio: d12-gpio-pins { ++ pinctrl-single,pins = < ++ /* (Y2) WKUP_GPIO0_50 */ ++ AM65X_WKUP_IOPAD(0x0098, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d12_gpio_pullup: d12-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (Y2) WKUP_GPIO0_50 */ ++ AM65X_WKUP_IOPAD(0x0098, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d12_gpio_pulldown: d12-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (Y2) WKUP_GPIO0_50 */ ++ AM65X_WKUP_IOPAD(0x0098, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d13_spi0_clk: d13-spi0-clk-pins { ++ pinctrl-single,pins = < ++ /* (Y1) MCU_SPI0_CLK */ ++ AM65X_WKUP_IOPAD(0x0090, PIN_INPUT, 0) ++ >; ++ }; ++ ++ d13_gpio: d13-gpio-pins { ++ pinctrl-single,pins = < ++ /* (Y1) WKUP_GPIO0_48 */ ++ AM65X_WKUP_IOPAD(0x0090, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d13_gpio_pullup: d13-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (Y1) WKUP_GPIO0_48 */ ++ AM65X_WKUP_IOPAD(0x0090, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d13_gpio_pulldown: d13-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (Y1) WKUP_GPIO0_48 */ ++ AM65X_WKUP_IOPAD(0x0090, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ a0_gpio: a0-gpio-pins { ++ pinctrl-single,pins = < ++ /* (L6) WKUP_GPIO0_45 */ ++ AM65X_WKUP_IOPAD(0x0084, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a0_gpio_pullup: a0-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (L6) WKUP_GPIO0_45 */ ++ AM65X_WKUP_IOPAD(0x0084, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a0_gpio_pulldown: a0-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (L6) WKUP_GPIO0_45 */ ++ AM65X_WKUP_IOPAD(0x0084, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ a1_gpio: a1-gpio-pins { ++ pinctrl-single,pins = < ++ /* (M6) WKUP_GPIO0_44 */ ++ AM65X_WKUP_IOPAD(0x0080, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a1_gpio_pullup: a1-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (M6) WKUP_GPIO0_44 */ ++ AM65X_WKUP_IOPAD(0x0080, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a1_gpio_pulldown: a1-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (M6) WKUP_GPIO0_44 */ ++ AM65X_WKUP_IOPAD(0x0080, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ a2_gpio: a2-gpio-pins { ++ pinctrl-single,pins = < ++ /* (L5) WKUP_GPIO0_43 */ ++ AM65X_WKUP_IOPAD(0x007C, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a2_gpio_pullup: a2-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (L5) WKUP_GPIO0_43 */ ++ AM65X_WKUP_IOPAD(0x007C, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a2_gpio_pulldown: a2-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (L5) WKUP_GPIO0_43 */ ++ AM65X_WKUP_IOPAD(0x007C, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ a3_gpio: a3-gpio-pins { ++ pinctrl-single,pins = < ++ /* (M5) WKUP_GPIO0_39 */ ++ AM65X_WKUP_IOPAD(0x006C, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a3_gpio_pullup: a3-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (M5) WKUP_GPIO0_39 */ ++ AM65X_WKUP_IOPAD(0x006C, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a3_gpio_pulldown: a3-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (M5) WKUP_GPIO0_39 */ ++ AM65X_WKUP_IOPAD(0x006C, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ a4_gpio: a4-gpio-pins { ++ pinctrl-single,pins = < ++ /* (L2) WKUP_GPIO0_42 */ ++ AM65X_WKUP_IOPAD(0x0078, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a4_gpio_pullup: a4-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (L2) WKUP_GPIO0_42 */ ++ AM65X_WKUP_IOPAD(0x0078, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a4_gpio_pulldown: a4-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (L2) WKUP_GPIO0_42 */ ++ AM65X_WKUP_IOPAD(0x0078, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ a5_gpio: a5-gpio-pins { ++ pinctrl-single,pins = < ++ /* (N5) WKUP_GPIO0_35 */ ++ AM65X_WKUP_IOPAD(0x005C, PIN_INPUT, 7) ++ >; ++ }; ++ ++ a5_gpio_pullup: a5-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (N5) WKUP_GPIO0_35 */ ++ AM65X_WKUP_IOPAD(0x005C, PIN_INPUT_PULLUP, 7) ++ >; ++ }; ++ ++ a5_gpio_pulldown: a5-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (N5) WKUP_GPIO0_35 */ ++ AM65X_WKUP_IOPAD(0x005C, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ + wkup_i2c0_pins_default: wkup-i2c0-default-pins { + pinctrl-single,pins = < + /* (AC7) WKUP_I2C0_SCL */ +@@ -146,23 +643,6 @@ + >; + }; + +- arduino_uart_pins_default: arduino-uart-default-pins { +- pinctrl-single,pins = < +- /* (P4) MCU_UART0_RXD */ +- AM65X_WKUP_IOPAD(0x0044, PIN_INPUT, 4) +- /* (P5) MCU_UART0_TXD */ +- AM65X_WKUP_IOPAD(0x0048, PIN_OUTPUT, 4) +- >; +- }; +- +- arduino_io_d2_to_d3_pins_default: arduino-io-d2-to-d3-default-pins { +- pinctrl-single,pins = < +- /* (P1) WKUP_GPIO0_31 */ +- AM65X_WKUP_IOPAD(0x004C, PIN_OUTPUT, 7) +- /* (N3) WKUP_GPIO0_33 */ +- AM65X_WKUP_IOPAD(0x0054, PIN_OUTPUT, 7) +- >; +- }; + + arduino_io_oe_pins_default: arduino-io-oe-default-pins { + pinctrl-single,pins = < +@@ -242,6 +722,220 @@ + }; + + &main_pmx0 { ++ pinctrl-names = ++ "default", ++ "d4-ehrpwm0-a", "d4-gpio", "d4-gpio-pullup", "d4-gpio-pulldown", ++ "d5-ehrpwm1-a", "d5-gpio", "d5-gpio-pullup", "d5-gpio-pulldown", ++ "d6-ehrpwm2-a", "d6-gpio", "d6-gpio-pullup", "d6-gpio-pulldown", ++ "d7-ehrpwm3-a", "d7-gpio", "d7-gpio-pullup", "d7-gpio-pulldown", ++ "d8-ehrpwm4-a", "d8-gpio", "d8-gpio-pullup", "d8-gpio-pulldown", ++ "d9-ehrpwm5-a", "d9-gpio", "d9-gpio-pullup", "d9-gpio-pulldown"; ++ ++ pinctrl-0 = <&d4_ehrpwm0_a>; ++ pinctrl-1 = <&d4_ehrpwm0_a>; ++ pinctrl-2 = <&d4_gpio>; ++ pinctrl-3 = <&d4_gpio_pullup>; ++ pinctrl-4 = <&d4_gpio_pulldown>; ++ ++ pinctrl-5 = <&d5_ehrpwm1_a>; ++ pinctrl-6 = <&d5_gpio>; ++ pinctrl-7 = <&d5_gpio_pullup>; ++ pinctrl-8 = <&d5_gpio_pulldown>; ++ ++ pinctrl-9 = <&d6_ehrpwm2_a>; ++ pinctrl-10 = <&d6_gpio>; ++ pinctrl-11 = <&d6_gpio_pullup>; ++ pinctrl-12 = <&d6_gpio_pulldown>; ++ ++ pinctrl-13 = <&d7_ehrpwm3_a>; ++ pinctrl-14 = <&d7_gpio>; ++ pinctrl-15 = <&d7_gpio_pullup>; ++ pinctrl-16 = <&d7_gpio_pulldown>; ++ ++ pinctrl-17 = <&d8_ehrpwm4_a>; ++ pinctrl-18 = <&d8_gpio>; ++ pinctrl-19 = <&d8_gpio_pullup>; ++ pinctrl-20 = <&d8_gpio_pulldown>; ++ ++ pinctrl-21 = <&d9_ehrpwm5_a>; ++ pinctrl-22 = <&d9_gpio>; ++ pinctrl-23 = <&d9_gpio_pullup>; ++ pinctrl-24 = <&d9_gpio_pulldown>; ++ ++ d4_ehrpwm0_a: d4-ehrpwm0-a-pins { ++ pinctrl-single,pins = < ++ /* (AG18) EHRPWM0_A */ ++ AM65X_IOPAD(0x0084, PIN_OUTPUT, 5) ++ >; ++ }; ++ ++ d4_gpio: d4-gpio-pins { ++ pinctrl-single,pins = < ++ /* (AG18) GPIO0_33 */ ++ AM65X_IOPAD(0x0084, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d4_gpio_pullup: d4-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (AG18) GPIO0_33 */ ++ AM65X_IOPAD(0x0084, PIN_INPUT_PULLUP, 7) ++ >; ++ }; ++ ++ d4_gpio_pulldown: d4-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (AG18) GPIO0_33 */ ++ AM65X_IOPAD(0x0084, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d5_ehrpwm1_a: d5-ehrpwm1-a-pins { ++ pinctrl-single,pins = < ++ /* (AF17) EHRPWM1_A */ ++ AM65X_IOPAD(0x008C, PIN_OUTPUT, 5) ++ >; ++ }; ++ ++ d5_gpio: d5-gpio-pins { ++ pinctrl-single,pins = < ++ /* (AF17) GPIO0_35 */ ++ AM65X_IOPAD(0x008C, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d5_gpio_pullup: d5-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (AF17) GPIO0_35 */ ++ AM65X_IOPAD(0x008C, PIN_INPUT_PULLUP, 7) ++ >; ++ }; ++ ++ d5_gpio_pulldown: d5-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (AF17) GPIO0_35 */ ++ AM65X_IOPAD(0x008C, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d6_ehrpwm2_a: d6-ehrpwm2-a-pins { ++ pinctrl-single,pins = < ++ /* (AH16) EHRPWM2_A */ ++ AM65X_IOPAD(0x0098, PIN_OUTPUT, 5) ++ >; ++ }; ++ ++ d6_gpio: d6-gpio-pins { ++ pinctrl-single,pins = < ++ /* (AH16) GPIO0_38 */ ++ AM65X_IOPAD(0x0098, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d6_gpio_pullup: d6-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (AH16) GPIO0_38 */ ++ AM65X_IOPAD(0x0098, PIN_INPUT_PULLUP, 7) ++ >; ++ }; ++ ++ d6_gpio_pulldown: d6-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (AH16) GPIO0_38 */ ++ AM65X_IOPAD(0x0098, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d7_ehrpwm3_a: d7-ehrpwm3-a-pins { ++ pinctrl-single,pins = < ++ /* (AH15) EHRPWM3_A */ ++ AM65X_IOPAD(0x00AC, PIN_OUTPUT, 5) ++ >; ++ }; ++ ++ d7_gpio: d7-gpio-pins { ++ pinctrl-single,pins = < ++ /* (AH15) GPIO0_43 */ ++ AM65X_IOPAD(0x00AC, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d7_gpio_pullup: d7-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (AH15) GPIO0_43 */ ++ AM65X_IOPAD(0x00AC, PIN_INPUT_PULLUP, 7) ++ >; ++ }; ++ ++ d7_gpio_pulldown: d7-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (AH15) GPIO0_43 */ ++ AM65X_IOPAD(0x00AC, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d8_ehrpwm4_a: d8-ehrpwm4-a-pins { ++ pinctrl-single,pins = < ++ /* (AG15) EHRPWM4_A */ ++ AM65X_IOPAD(0x00C0, PIN_OUTPUT, 5) ++ >; ++ }; ++ ++ d8_gpio: d8-gpio-pins { ++ pinctrl-single,pins = < ++ /* (AG15) GPIO0_48 */ ++ AM65X_IOPAD(0x00C0, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d8_gpio_pullup: d8-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (AG15) GPIO0_48 */ ++ AM65X_IOPAD(0x00C0, PIN_INPUT_PULLUP, 7) ++ >; ++ }; ++ ++ d8_gpio_pulldown: d8-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (AG15) GPIO0_48 */ ++ AM65X_IOPAD(0x00C0, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ d9_ehrpwm5_a: d9-ehrpwm5-a-pins { ++ pinctrl-single,pins = < ++ /* (AD15) EHRPWM5_A */ ++ AM65X_IOPAD(0x00CC, PIN_OUTPUT, 5) ++ >; ++ }; ++ ++ d9_gpio: d9-gpio-pins { ++ pinctrl-single,pins = < ++ /* (AD15) GPIO0_51 */ ++ AM65X_IOPAD(0x00CC, PIN_INPUT, 7) ++ >; ++ }; ++ ++ d9_gpio_pullup: d9-gpio-pullup-pins { ++ pinctrl-single,pins = < ++ /* (AD15) GPIO0_51 */ ++ AM65X_IOPAD(0x00CC, PIN_INPUT_PULLUP, 7) ++ >; ++ }; ++ ++ d9_gpio_pulldown: d9-gpio-pulldown-pins { ++ pinctrl-single,pins = < ++ /* (AD15) GPIO0_51 */ ++ AM65X_IOPAD(0x00CC, PIN_INPUT_PULLDOWN, 7) ++ >; ++ }; ++ ++ main_pcie_enable_pins_default: main-pcie-enable-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x01c4, PIN_INPUT_PULLUP, 7) /* (AH13) GPIO1_17 */ ++ >; ++ }; ++ + main_uart1_pins_default: main-uart1-default-pins { + pinctrl-single,pins = < + AM65X_IOPAD(0x0174, PIN_INPUT, 6) /* (AE23) UART1_RXD */ +@@ -283,17 +977,6 @@ + >; + }; + +- arduino_io_d4_to_d9_pins_default: arduino-io-d4-to-d9-default-pins { +- pinctrl-single,pins = < +- AM65X_IOPAD(0x0084, PIN_OUTPUT, 7) /* (AG18) GPIO0_33 */ +- AM65X_IOPAD(0x008C, PIN_OUTPUT, 7) /* (AF17) GPIO0_35 */ +- AM65X_IOPAD(0x0098, PIN_OUTPUT, 7) /* (AH16) GPIO0_38 */ +- AM65X_IOPAD(0x00AC, PIN_OUTPUT, 7) /* (AH15) GPIO0_43 */ +- AM65X_IOPAD(0x00C0, PIN_OUTPUT, 7) /* (AG15) GPIO0_48 */ +- AM65X_IOPAD(0x00CC, PIN_OUTPUT, 7) /* (AD15) GPIO0_51 */ +- >; +- }; +- + dss_vout1_pins_default: dss-vout1-default-pins { + pinctrl-single,pins = < + AM65X_IOPAD(0x0000, PIN_OUTPUT, 1) /* VOUT1_DATA0 */ +@@ -339,6 +1022,43 @@ + AM65X_IOPAD(0x0070, PIN_INPUT, 5) /* (R25) I2C2_SDA */ + >; + }; ++ ++ icssg0_mdio_pins_default: icssg0-mdio-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x0294, PIN_INPUT, 0) /* (AE26) PRG0_MDIO0_MDIO */ ++ AM65X_IOPAD(0x0298, PIN_OUTPUT, 0) /* (AE28) PRG0_MDIO0_MDC */ ++ >; ++ }; ++ ++ icssg0_rgmii_pins_default: icssg0-rgmii-default-pins { ++ pinctrl-single,pins = < ++ AM65X_IOPAD(0x0244, PIN_INPUT, 2) /* (AB28) PRG0_PRU1_GPO0.PRG0_RGMII2_RD0 */ ++ AM65X_IOPAD(0x0248, PIN_INPUT, 2) /* (AC28) PRG0_PRU1_GPO1.PRG0_RGMII2_RD1 */ ++ AM65X_IOPAD(0x024c, PIN_INPUT, 2) /* (AC27) PRG0_PRU1_GPO2.PRG0_RGMII2_RD2 */ ++ AM65X_IOPAD(0x0250, PIN_INPUT, 2) /* (AB26) PRG0_PRU1_GPO3.PRG0_RGMII2_RD3 */ ++ AM65X_IOPAD(0x0274, PIN_OUTPUT, 2) /* (AC25) PRG0_PRU1_GPO12.PRG0_RGMII2_TD0 */ ++ AM65X_IOPAD(0x0278, PIN_OUTPUT, 2) /* (AD25) PRG0_PRU1_GPO13.PRG0_RGMII2_TD1 */ ++ AM65X_IOPAD(0x027c, PIN_OUTPUT, 2) /* (AD24) PRG0_PRU1_GPO14.PRG0_RGMII2_TD2 */ ++ AM65X_IOPAD(0x0280, PIN_OUTPUT, 2) /* (AE27) PRG0_PRU1_GPO15.PRG0_RGMII2_TD3 */ ++ AM65X_IOPAD(0x0284, PIN_INPUT, 2) /* (AC24) PRG0_PRU1_GPO16.PRG0_RGMII2_TXC */ ++ AM65X_IOPAD(0x0270, PIN_OUTPUT, 2) /* (AB24) PRG0_PRU1_GPO11.PRG0_RGMII2_TX_CTL */ ++ AM65X_IOPAD(0x025c, PIN_INPUT, 2) /* (AB27) PRG0_PRU1_GPO6.PRG0_RGMII2_RXC */ ++ AM65X_IOPAD(0x0254, PIN_INPUT, 2) /* (AA25) PRG0_PRU1_GPO4.PRG0_RGMII2_RX_CTL */ ++ ++ AM65X_IOPAD(0x01f4, PIN_INPUT, 2) /* (V24) PRG0_PRU0_GPO0.PRG0_RGMII1_RD0 */ ++ AM65X_IOPAD(0x01f8, PIN_INPUT, 2) /* (W25) PRG0_PRU0_GPO1.PRG0_RGMII1_RD1 */ ++ AM65X_IOPAD(0x01fc, PIN_INPUT, 2) /* (W24) PRG0_PRU0_GPO2.PRG0_RGMII1_RD2 */ ++ AM65X_IOPAD(0x0200, PIN_INPUT, 2) /* (AA27) PRG0_PRU0_GPO3.PRG0_RGMII1_RD3 */ ++ AM65X_IOPAD(0x0224, PIN_OUTPUT, 2) /* (AD27) PRG0_PRU0_GPO12.PRG0_RGMII1_TD0 */ ++ AM65X_IOPAD(0x0228, PIN_OUTPUT, 2) /* (AC26) PRG0_PRU0_GPO13.PRG0_RGMII1_TD1 */ ++ AM65X_IOPAD(0x022c, PIN_OUTPUT, 2) /* (AD26) PRG0_PRU0_GPO14.PRG0_RGMII1_TD2 */ ++ AM65X_IOPAD(0x0230, PIN_OUTPUT, 2) /* (AA24) PRG0_PRU0_GPO15.PRG0_RGMII1_TD3 */ ++ AM65X_IOPAD(0x0234, PIN_INPUT, 2) /* (AD28) PRG0_PRU0_GPO16.PRG0_RGMII1_TXC */ ++ AM65X_IOPAD(0x0220, PIN_OUTPUT, 2) /* (AB25) PRG0_PRU0_GPO11.PRG0_RGMII1_TX_CTL */ ++ AM65X_IOPAD(0x020c, PIN_INPUT, 2) /* (Y25) PRG0_PRU0_GPO6.PRG0_RGMII1_RXC */ ++ AM65X_IOPAD(0x0204, PIN_INPUT, 2) /* (Y24) PRG0_PRU0_GPO4.PRG0_RGMII1_RX_CTL */ ++ >; ++ }; + }; + + &main_pmx1 { +@@ -355,12 +1075,6 @@ + AM65X_IOPAD(0x000c, PIN_INPUT, 0) /* (E21) I2C1_SDA */ + >; + }; +- +- ecap0_pins_default: ecap0-default-pins { +- pinctrl-single,pins = < +- AM65X_IOPAD(0x0010, PIN_INPUT, 0) /* (D21) ECAP0_IN_APWM_OUT */ +- >; +- }; + }; + + &wkup_uart0 { +@@ -376,13 +1090,9 @@ + + &mcu_uart0 { + status = "okay"; +- pinctrl-names = "default"; +- pinctrl-0 = <&arduino_uart_pins_default>; + }; + + &main_gpio0 { +- pinctrl-names = "default"; +- pinctrl-0 = <&arduino_io_d4_to_d9_pins_default>; + gpio-line-names = + "main_gpio0-base", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", +@@ -392,10 +1102,14 @@ + "", "IO9"; + }; + ++&main_gpio1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_pcie_enable_pins_default>; ++}; ++ + &wkup_gpio0 { + pinctrl-names = "default"; + pinctrl-0 = +- <&arduino_io_d2_to_d3_pins_default>, + <&arduino_i2c_aio_switch_pins_default>, + <&arduino_io_oe_pins_default>, + <&push_button_pins_default>, +@@ -557,13 +1271,8 @@ + status = "disabled"; + }; + +-&ecap0 { +- status = "okay"; +- pinctrl-names = "default"; +- pinctrl-0 = <&ecap0_pins_default>; +-}; +- + &sdhci1 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; + ti,driver-strength-ohm = <50>; +@@ -584,9 +1293,6 @@ + + &mcu_spi0 { + status = "okay"; +- pinctrl-names = "default"; +- pinctrl-0 = <&mcu_spi0_pins_default>; +- + #address-cells = <1>; + #size-cells = <0>; + ti,pindir-d0-out-d1-in; +@@ -718,11 +1424,33 @@ + &mcu_r5fss0_core0 { + memory-region = <&mcu_r5fss0_core0_dma_memory_region>, + <&mcu_r5fss0_core0_memory_region>; +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + }; + + &mcu_r5fss0_core1 { + memory-region = <&mcu_r5fss0_core1_dma_memory_region>, + <&mcu_r5fss0_core1_memory_region>; +- mboxes = <&mailbox0_cluster1>, <&mbox_mcu_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster1 &mbox_mcu_r5fss0_core1>; ++}; ++ ++&mcu_rti1 { ++ memory-region = <&wdt_reset_memory_region>; ++}; ++ ++&icssg0_mdio { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&icssg0_mdio_pins_default>; ++ ++ icssg0_eth0_phy: ethernet-phy@0 { ++ reg = <0>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ }; ++ ++ icssg0_eth1_phy: ethernet-phy@1 { ++ reg = <1>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg1.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg1.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg1.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg1.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * Copyright (c) Siemens AG, 2021 ++ * Copyright (c) Siemens AG, 2021-2023 + * + * Authors: + * Jan Kiszka +@@ -44,3 +44,11 @@ + &tx_pru2_1 { + status = "disabled"; + }; ++ ++&icssg0_eth { ++ status = "disabled"; ++}; ++ ++&icssg0_mdio { ++ status = "disabled"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg2.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg2.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg2.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common-pg2.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -20,7 +20,9 @@ + + &main_gpio1 { + pinctrl-names = "default"; +- pinctrl-0 = <&cp2102n_reset_pin_default>; ++ pinctrl-0 = ++ <&main_pcie_enable_pins_default>, ++ <&cp2102n_reset_pin_default>; + gpio-line-names = + "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -449,6 +449,7 @@ + ti,otap-del-sel-hs400 = <0x0>; + ti,trm-icp = <0x8>; + dma-coherent; ++ status = "disabled"; + }; + + sdhci1: mmc@4fa0000 { +@@ -471,6 +472,7 @@ + ti,clkbuf-sel = <0x7>; + ti,trm-icp = <0x8>; + dma-coherent; ++ status = "disabled"; + }; + + scm_conf: scm-conf@100000 { +@@ -498,8 +500,8 @@ + }; + + dss_oldi_io_ctrl: dss-oldi-io-ctrl@41e0 { +- compatible = "syscon"; +- reg = <0x000041e0 0x14>; ++ compatible = "ti,am654-dss-oldi-io-ctrl", "syscon"; ++ reg = <0x41e0 0x14>; + }; + + ehrpwm_tbclk: clock-controller@4140 { +@@ -600,7 +602,7 @@ + }; + + main_navss: bus@30800000 { +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x30800000 0x0 0x30800000 0x0 0xbc00000>; +@@ -790,8 +792,12 @@ + compatible = "ti,am654-navss-main-udmap"; + reg = <0x0 0x31150000 0x0 0x100>, + <0x0 0x34000000 0x0 0x100000>, +- <0x0 0x35000000 0x0 0x100000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x0 0x35000000 0x0 0x100000>, ++ <0x0 0x30b00000 0x0 0x10000>, ++ <0x0 0x30c00000 0x0 0x10000>, ++ <0x0 0x30d00000 0x0 0x8000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&inta_main_udmass>; + #dma-cells = <1>; + +@@ -880,20 +886,6 @@ + status = "disabled"; + }; + +- pcie0_ep: pcie-ep@5500000 { +- compatible = "ti,am654-pcie-ep"; +- reg = <0x0 0x5500000 0x0 0x1000>, <0x0 0x5501000 0x0 0x1000>, <0x0 0x10000000 0x0 0x8000000>, <0x0 0x5506000 0x0 0x1000>; +- reg-names = "app", "dbics", "addr_space", "atu"; +- power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>; +- ti,syscon-pcie-mode = <&scm_conf 0x4060>; +- num-ib-windows = <16>; +- num-ob-windows = <16>; +- max-link-speed = <2>; +- dma-coherent; +- interrupts = ; +- status = "disabled"; +- }; +- + pcie1_rc: pcie@5600000 { + compatible = "ti,am654-pcie-rc"; + reg = <0x0 0x5600000 0x0 0x1000>, <0x0 0x5601000 0x0 0x1000>, <0x0 0x18000000 0x0 0x2000>, <0x0 0x5606000 0x0 0x1000>; +@@ -915,20 +907,6 @@ + status = "disabled"; + }; + +- pcie1_ep: pcie-ep@5600000 { +- compatible = "ti,am654-pcie-ep"; +- reg = <0x0 0x5600000 0x0 0x1000>, <0x0 0x5601000 0x0 0x1000>, <0x0 0x18000000 0x0 0x4000000>, <0x0 0x5606000 0x0 0x1000>; +- reg-names = "app", "dbics", "addr_space", "atu"; +- power-domains = <&k3_pds 121 TI_SCI_PD_EXCLUSIVE>; +- ti,syscon-pcie-mode = <&scm_conf 0x4070>; +- num-ib-windows = <16>; +- num-ob-windows = <16>; +- max-link-speed = <2>; +- dma-coherent; +- interrupts = ; +- status = "disabled"; +- }; +- + mcasp0: mcasp@2b00000 { + compatible = "ti,am33xx-mcasp-audio"; + reg = <0x0 0x02b00000 0x0 0x2000>, +@@ -1013,9 +991,10 @@ + <0x0 0x04a07000 0x0 0x1000>, /* ovr1 */ + <0x0 0x04a08000 0x0 0x1000>, /* ovr2 */ + <0x0 0x04a0a000 0x0 0x1000>, /* vp1 */ +- <0x0 0x04a0b000 0x0 0x1000>; /* vp2 */ ++ <0x0 0x04a0b000 0x0 0x1000>, /* vp2 */ ++ <0x0 0x04a01000 0x0 0x1000>; /* common1 */ + reg-names = "common", "vidl1", "vid", +- "ovr1", "ovr2", "vp1", "vp2"; ++ "ovr1", "ovr2", "vp1", "vp2", "common1"; + + ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>; + +@@ -1151,6 +1130,18 @@ + }; + }; + ++ icssg0_iep0: iep@2e000 { ++ compatible = "ti,am654-icss-iep"; ++ reg = <0x2e000 0x1000>; ++ clocks = <&icssg0_iepclk_mux>; ++ }; ++ ++ icssg0_iep1: iep@2f000 { ++ compatible = "ti,am654-icss-iep"; ++ reg = <0x2f000 0x1000>; ++ clocks = <&icssg0_iepclk_mux>; ++ }; ++ + icssg0_mii_rt: mii-rt@32000 { + compatible = "ti,pruss-mii", "syscon"; + reg = <0x32000 0x100>; +@@ -1293,6 +1284,18 @@ + }; + }; + ++ icssg1_iep0: iep@2e000 { ++ compatible = "ti,am654-icss-iep"; ++ reg = <0x2e000 0x1000>; ++ clocks = <&icssg1_iepclk_mux>; ++ }; ++ ++ icssg1_iep1: iep@2f000 { ++ compatible = "ti,am654-icss-iep"; ++ reg = <0x2f000 0x1000>; ++ clocks = <&icssg1_iepclk_mux>; ++ }; ++ + icssg1_mii_rt: mii-rt@32000 { + compatible = "ti,pruss-mii", "syscon"; + reg = <0x32000 0x100>; +@@ -1435,6 +1438,18 @@ + }; + }; + ++ icssg2_iep0: iep@2e000 { ++ compatible = "ti,am654-icss-iep"; ++ reg = <0x2e000 0x1000>; ++ clocks = <&icssg2_iepclk_mux>; ++ }; ++ ++ icssg2_iep1: iep@2f000 { ++ compatible = "ti,am654-icss-iep"; ++ reg = <0x2f000 0x1000>; ++ clocks = <&icssg2_iepclk_mux>; ++ }; ++ + icssg2_mii_rt: mii-rt@32000 { + compatible = "ti,pruss-mii", "syscon"; + reg = <0x32000 0x100>; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -185,7 +185,7 @@ + }; + + mcu_navss: bus@28380000 { +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>; +@@ -214,8 +214,12 @@ + compatible = "ti,am654-navss-mcu-udmap"; + reg = <0x0 0x285c0000 0x0 0x100>, + <0x0 0x2a800000 0x0 0x40000>, +- <0x0 0x2aa00000 0x0 0x40000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x0 0x2aa00000 0x0 0x40000>, ++ <0x0 0x284a0000 0x0 0x4000>, ++ <0x0 0x284c0000 0x0 0x4000>, ++ <0x0 0x28400000 0x0 0x2000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&inta_main_udmass>; + #dma-cells = <1>; + +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -34,9 +34,16 @@ + }; + }; + +- chipid@43000014 { +- compatible = "ti,am654-chipid"; +- reg = <0x43000014 0x4>; ++ wkup_conf: bus@43000000 { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x43000000 0x20000>; ++ ++ chipid: chipid@14 { ++ compatible = "ti,am654-chipid"; ++ reg = <0x14 0x4>; ++ }; + }; + + wkup_pmx0: pinctrl@4301c000 { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts +--- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -31,6 +31,7 @@ + can1 = &mcu_mcan1; + can2 = &main_mcan6; + can3 = &main_mcan7; ++ ethernet0 = &cpsw_port1; + }; + + vusb_main: regulator-vusb-main5v0 { +@@ -168,6 +169,13 @@ + }; + }; + }; ++ ++ csi_mux: mux-controller { ++ compatible = "gpio-mux"; ++ #mux-state-cells = <1>; ++ mux-gpios = <&exp3 1 GPIO_ACTIVE_HIGH>; ++ idle-state = <0>; ++ }; + }; + + &main_pmx0 { +@@ -185,6 +193,13 @@ + >; + }; + ++ main_i2c1_pins_default: main-i2c1-default-pins { ++ pinctrl-single,pins = < ++ J721S2_IOPAD(0x0ac, PIN_INPUT, 13) /* (AC25) MCASP0_AXR15.I2C1_SCL */ ++ J721S2_IOPAD(0x0b0, PIN_INPUT, 13) /* (AD26) MCASP1_AXR3.I2C1_SDA */ ++ >; ++ }; ++ + main_mmc1_pins_default: main-mmc1-default-pins { + pinctrl-single,pins = < + J721S2_IOPAD(0x104, PIN_INPUT, 0) /* (P23) MMC1_CLK */ +@@ -430,6 +445,42 @@ + }; + }; + ++&main_i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c1_pins_default>; ++ status = "okay"; ++ ++ exp3: gpio@20 { ++ compatible = "ti,tca6408"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ gpio-line-names = "CSI_VIO_SEL", "CSI_SEL_FPC_EXPn", ++ "IO_EXP_CSI2_EXP_RSTz","CSI0_B_GPIO1", ++ "CSI1_B_GPIO1"; ++ }; ++ ++ i2c-mux@70 { ++ compatible = "nxp,pca9543"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x70>; ++ ++ cam0_i2c: i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ }; ++ ++ cam1_i2c: i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ }; ++ ++ }; ++}; ++ + &main_i2c4 { + status = "okay"; + pinctrl-names = "default"; +@@ -553,3 +604,59 @@ + }; + }; + }; ++ ++&serdes_ln_ctrl { ++ idle-states = , , ++ , ; ++}; ++ ++&serdes_refclk { ++ clock-frequency = <100000000>; ++}; ++ ++&serdes0 { ++ status = "okay"; ++ ++ serdes0_pcie_link: phy@0 { ++ reg = <0>; ++ cdns,num-lanes = <2>; ++ #phy-cells = <0>; ++ cdns,phy-type = ; ++ resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>; ++ }; ++ ++ serdes0_usb_link: phy@2 { ++ status = "okay"; ++ reg = <2>; ++ cdns,num-lanes = <1>; ++ #phy-cells = <0>; ++ cdns,phy-type = ; ++ resets = <&serdes_wiz0 3>; ++ }; ++}; ++ ++&pcie1_rc { ++ status = "okay"; ++ reset-gpios = <&exp1 10 GPIO_ACTIVE_HIGH>; ++ phys = <&serdes0_pcie_link>; ++ phy-names = "pcie-phy"; ++ num-lanes = <2>; ++}; ++ ++&usb_serdes_mux { ++ idle-states = <0>; /* USB0 to SERDES lane 2 */ ++}; ++ ++&usbss0 { ++ status = "okay"; ++ pinctrl-0 = <&main_usbss0_pins_default>; ++ pinctrl-names = "default"; ++ ti,vbus-divider; ++}; ++ ++&usb0 { ++ dr_mode = "host"; ++ maximum-speed = "super-speed"; ++ phys = <&serdes0_usb_link>; ++ phy-names = "cdns3,usb3-phy"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi +--- a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -25,6 +25,108 @@ + reg = <0x00 0x9e800000 0x00 0x01800000>; + no-map; + }; ++ ++ mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa1000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa1100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa2000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core0_memory_region: r5f-memory@a2100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa2100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa3000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core1_memory_region: r5f-memory@a3100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa3100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa4000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core0_memory_region: r5f-memory@a4100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa4100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa5000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core1_memory_region: r5f-memory@a5100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa5100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ c71_0_dma_memory_region: c71-dma-memory@a6000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa6000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ c71_0_memory_region: c71-memory@a6100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa6100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ c71_1_dma_memory_region: c71-dma-memory@a7000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa7000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ c71_1_memory_region: c71-memory@a7100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa7100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ rtos_ipc_memory_region: ipc-memories@a8000000 { ++ reg = <0x00 0xa8000000 0x00 0x01c00000>; ++ alignment = <0x1000>; ++ no-map; ++ }; + }; + }; + +@@ -49,3 +151,109 @@ + reg = <0x51>; + }; + }; ++ ++&mailbox0_cluster0 { ++ status = "okay"; ++ interrupts = <436>; ++ mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster1 { ++ status = "okay"; ++ interrupts = <432>; ++ mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster2 { ++ status = "okay"; ++ interrupts = <428>; ++ mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster4 { ++ status = "okay"; ++ interrupts = <420>; ++ mbox_c71_0: mbox-c71-0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_c71_1: mbox-c71-1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mcu_r5fss0_core0 { ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; ++ memory-region = <&mcu_r5fss0_core0_dma_memory_region>, ++ <&mcu_r5fss0_core0_memory_region>; ++}; ++ ++&mcu_r5fss0_core1 { ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; ++ memory-region = <&mcu_r5fss0_core1_dma_memory_region>, ++ <&mcu_r5fss0_core1_memory_region>; ++}; ++ ++&main_r5fss0_core0 { ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; ++ memory-region = <&main_r5fss0_core0_dma_memory_region>, ++ <&main_r5fss0_core0_memory_region>; ++}; ++ ++&main_r5fss0_core1 { ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; ++ memory-region = <&main_r5fss0_core1_dma_memory_region>, ++ <&main_r5fss0_core1_memory_region>; ++}; ++ ++&main_r5fss1_core0 { ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; ++ memory-region = <&main_r5fss1_core0_dma_memory_region>, ++ <&main_r5fss1_core0_memory_region>; ++}; ++ ++&main_r5fss1_core1 { ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; ++ memory-region = <&main_r5fss1_core1_dma_memory_region>, ++ <&main_r5fss1_core1_memory_region>; ++}; ++ ++&c71_0 { ++ status = "okay"; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_0>; ++ memory-region = <&c71_0_dma_memory_region>, ++ <&c71_0_memory_region>; ++}; ++ ++&c71_1 { ++ status = "okay"; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_1>; ++ memory-region = <&c71_1_dma_memory_region>, ++ <&c71_1_memory_region>; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am69-sk.dts b/arch/arm64/boot/dts/ti/k3-am69-sk.dts +--- a/arch/arm64/boot/dts/ti/k3-am69-sk.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-am69-sk.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -1,6 +1,6 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* +- * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + * Design Files: https://www.ti.com/lit/zip/SPRR466 + * TRM: https://www.ti.com/lit/zip/spruj52 +@@ -33,6 +33,7 @@ + + memory@80000000 { + device_type = "memory"; ++ bootph-all; + /* 32G RAM */ + reg = <0x00 0x80000000 0x00 0x80000000>, + <0x08 0x80000000 0x07 0x80000000>; +@@ -47,6 +48,150 @@ + reg = <0x00 0x9e800000 0x00 0x01800000>; + no-map; + }; ++ ++ mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa1000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa1100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa2000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core0_memory_region: r5f-memory@a2100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa2100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa3000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core1_memory_region: r5f-memory@a3100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa3100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa4000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core0_memory_region: r5f-memory@a4100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa4100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa5000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core1_memory_region: r5f-memory@a5100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa5100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss2_core0_dma_memory_region: r5f-dma-memory@a6000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa6000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss2_core0_memory_region: r5f-memory@a6100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa6100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss2_core1_dma_memory_region: r5f-dma-memory@a7000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa7000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss2_core1_memory_region: r5f-memory@a7100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa7100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ c71_0_dma_memory_region: c71-dma-memory@a8000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa8000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ c71_0_memory_region: c71-memory@a8100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa8100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ c71_1_dma_memory_region: c71-dma-memory@a9000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa9000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ c71_1_memory_region: c71-memory@a9100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa9100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ c71_2_dma_memory_region: c71-dma-memory@aa000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xaa000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ c71_2_memory_region: c71-memory@aa100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xaa100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ c71_3_dma_memory_region: c71-dma-memory@ab000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xab000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ c71_3_memory_region: c71-memory@ab100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xab100000 0x00 0xf00000>; ++ no-map; ++ }; + }; + + vusb_main: regulator-vusb-main5v0 { +@@ -107,6 +252,108 @@ + states = <1800000 0x0>, + <3300000 0x1>; + }; ++ ++ dp0_pwr_3v3: regulator-dp0-pwr { ++ compatible = "regulator-fixed"; ++ regulator-name = "dp0-pwr"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dp_pwr_en_pins_default>; ++ gpio = <&main_gpio0 4 0>; /* DP0_3V3 _EN */ ++ enable-active-high; ++ }; ++ ++ dp0: connector-dp0 { ++ compatible = "dp-connector"; ++ label = "DP0"; ++ type = "full-size"; ++ dp-pwr-supply = <&dp0_pwr_3v3>; ++ ++ port { ++ dp0_connector_in: endpoint { ++ remote-endpoint = <&dp0_out>; ++ }; ++ }; ++ }; ++ ++ connector-hdmi { ++ compatible = "hdmi-connector"; ++ label = "hdmi"; ++ type = "a"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmi_hpd_pins_default>; ++ ddc-i2c-bus = <&mcu_i2c1>; ++ hpd-gpios = <&main_gpio0 0 GPIO_ACTIVE_HIGH>; /* HDMI_HPD */ ++ ++ port { ++ hdmi_connector_in: endpoint { ++ remote-endpoint = <&tfp410_out>; ++ }; ++ }; ++ }; ++ ++ bridge-dvi { ++ compatible = "ti,tfp410"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&hdmi_pdn_pins_default>; ++ powerdown-gpios = <&wkup_gpio0 14 GPIO_ACTIVE_LOW>; /* HDMI_PDn */ ++ ti,deskew = <0>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ tfp410_in: endpoint { ++ remote-endpoint = <&dpi1_out0>; ++ pclk-sample = <1>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ tfp410_out: endpoint { ++ remote-endpoint = <&hdmi_connector_in>; ++ }; ++ }; ++ }; ++ }; ++ ++ csi_mux: mux-controller { ++ compatible = "gpio-mux"; ++ #mux-state-cells = <1>; ++ mux-gpios = <&exp2 1 GPIO_ACTIVE_HIGH>; ++ idle-state = <0>; ++ }; ++ ++ transceiver1: can-phy0 { ++ compatible = "ti,tcan1042"; ++ #phy-cells = <0>; ++ max-bitrate = <5000000>; ++ }; ++ ++ transceiver2: can-phy1 { ++ compatible = "ti,tcan1042"; ++ #phy-cells = <0>; ++ max-bitrate = <5000000>; ++ }; ++ ++ transceiver3: can-phy2 { ++ compatible = "ti,tcan1042"; ++ #phy-cells = <0>; ++ max-bitrate = <5000000>; ++ }; ++ ++ transceiver4: can-phy3 { ++ compatible = "ti,tcan1042"; ++ #phy-cells = <0>; ++ max-bitrate = <5000000>; ++ }; ++ + }; + + &main_pmx0 { +@@ -126,6 +373,13 @@ + >; + }; + ++ main_i2c1_pins_default: main-i2c1-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x0ac, PIN_INPUT_PULLUP, 13) /* (AE34) MCASP0_AXR15.I2C1_SCL */ ++ J784S4_IOPAD(0x0b0, PIN_INPUT_PULLUP, 13) /* (AL33) MCASP1_AXR3.I2C1_SDA */ ++ >; ++ }; ++ + main_mmc1_pins_default: main-mmc1-default-pins { + bootph-all; + pinctrl-single,pins = < +@@ -164,10 +418,102 @@ + J784S4_IOPAD(0x004, PIN_INPUT, 7) /* (AG36) MCAN12_TX.GPIO0_1 */ + >; + }; ++ ++ dp0_pins_default: dp0-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x014, PIN_INPUT, 13) /* (AG33) MCAN14_TX.DP0_HPD */ ++ >; ++ }; ++ ++ dp_pwr_en_pins_default: dp-pwr-en-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x010, PIN_INPUT, 7) /* (AH33) MCAN13_RX.GPIO0_4 */ ++ >; ++ }; ++ ++ dss_vout0_pins_default: dss-vout0-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x074, PIN_OUTPUT, 2) /* (AC33) MCAN2_TX.VOUT0_DATA0 */ ++ J784S4_IOPAD(0x070, PIN_OUTPUT, 2) /* (AH38) MCAN1_RX.VOUT0_DATA1 */ ++ J784S4_IOPAD(0x07c, PIN_OUTPUT, 2) /* (AJ38) MCASP0_AXR3.VOUT0_DATA2 */ ++ J784S4_IOPAD(0x068, PIN_OUTPUT, 2) /* (AE38) MCAN0_RX.VOUT0_DATA3 */ ++ J784S4_IOPAD(0x064, PIN_OUTPUT, 2) /* (AF38) MCAN0_TX.VOUT0_DATA4 */ ++ J784S4_IOPAD(0x060, PIN_OUTPUT, 2) /* (AE36) MCASP2_AXR1.VOUT0_DATA5 */ ++ J784S4_IOPAD(0x05c, PIN_OUTPUT, 2) /* (AC36) MCASP2_AXR0.VOUT0_DATA6 */ ++ J784S4_IOPAD(0x058, PIN_OUTPUT, 2) /* (AE37) MCASP2_AFSX.VOUT0_DATA7 */ ++ J784S4_IOPAD(0x054, PIN_OUTPUT, 2) /* (AD37) MCASP2_ACLKX.VOUT0_DATA8 */ ++ J784S4_IOPAD(0x050, PIN_OUTPUT, 2) /* (AC37) MCASP1_AXR2.VOUT0_DATA9 */ ++ J784S4_IOPAD(0x04c, PIN_OUTPUT, 2) /* (AC32) MCASP1_AXR1.VOUT0_DATA10 */ ++ J784S4_IOPAD(0x048, PIN_OUTPUT, 2) /* (AK33) MCASP0_AXR2.VOUT0_DATA11 */ ++ J784S4_IOPAD(0x044, PIN_OUTPUT, 2) /* (AG37) MCASP0_AXR1.VOUT0_DATA12 */ ++ J784S4_IOPAD(0x040, PIN_OUTPUT, 2) /* (AF37) MCASP0_AXR0.VOUT0_DATA13 */ ++ J784S4_IOPAD(0x03c, PIN_OUTPUT, 2) /* (AK38) MCASP0_AFSX.VOUT0_DATA14 */ ++ J784S4_IOPAD(0x038, PIN_OUTPUT, 2) /* (AK35) MCASP0_ACLKX.VOUT0_DATA15 */ ++ J784S4_IOPAD(0x0c8, PIN_OUTPUT, 2) /* (AJ32) EXT_REFCLK1.VOUT0_DATA16 */ ++ J784S4_IOPAD(0x030, PIN_OUTPUT, 2) /* (AK37) GPIO0_12.VOUT0_DATA17 */ ++ J784S4_IOPAD(0x02c, PIN_OUTPUT, 2) /* (AL32) GPIO0_11.VOUT0_DATA18 */ ++ J784S4_IOPAD(0x028, PIN_OUTPUT, 2) /* (AE33) MCAN16_RX.VOUT0_DATA19 */ ++ J784S4_IOPAD(0x024, PIN_OUTPUT, 2) /* (AH34) MCAN16_TX.VOUT0_DATA20 */ ++ J784S4_IOPAD(0x020, PIN_OUTPUT, 2) /* (AJ35) MCAN15_RX.VOUT0_DATA21 */ ++ J784S4_IOPAD(0x01c, PIN_OUTPUT, 2) /* (AG34) MCAN15_TX.VOUT0_DATA22 */ ++ J784S4_IOPAD(0x018, PIN_OUTPUT, 2) /* (AK36) MCAN14_RX.VOUT0_DATA23 */ ++ J784S4_IOPAD(0x084, PIN_OUTPUT, 2) /* (AG38) MCASP0_AXR5.VOUT0_DE */ ++ J784S4_IOPAD(0x080, PIN_OUTPUT, 2) /* (AK34) MCASP0_AXR4.VOUT0_HSYNC */ ++ J784S4_IOPAD(0x078, PIN_OUTPUT, 2) /* (AH37) MCAN2_RX.VOUT0_PCLK */ ++ J784S4_IOPAD(0x088, PIN_OUTPUT, 2) /* (AF36) MCASP0_AXR6.VOUT0_VSYNC */ ++ >; ++ }; ++ ++ hdmi_hpd_pins_default: hdmi-hpd-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x000, PIN_INPUT, 7) /* (AN35) EXTINTN.GPIO0_0 */ ++ >; ++ }; ++ ++ main_mcan6_pins_default: main-mcan6-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x098, PIN_INPUT, 0) /* (AH36) MCAN6_RX */ ++ J784S4_IOPAD(0x094, PIN_OUTPUT, 0) /* (AG35) MCAN6_TX */ ++ >; ++ }; ++ ++ main_mcan7_pins_default: main-mcan7-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x0A0, PIN_INPUT, 0) /* (AD34) MCAN7_RX */ ++ J784S4_IOPAD(0x09C, PIN_OUTPUT, 0) /* (AF35) MCAN7_TX */ ++ >; ++ }; ++ ++}; ++ ++&wkup_pmx0 { ++ bootph-all; ++ mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { ++ pinctrl-single,pins = < ++ J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (E32) MCU_OSPI0_CLK */ ++ J784S4_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (A32) MCU_OSPI0_CSn0 */ ++ J784S4_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (B33) MCU_OSPI0_D0 */ ++ J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (B32) MCU_OSPI0_D1 */ ++ J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (C33) MCU_OSPI0_D2 */ ++ J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (C35) MCU_OSPI0_D3 */ ++ J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D33) MCU_OSPI0_D4 */ ++ J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D34) MCU_OSPI0_D5 */ ++ J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (E34) MCU_OSPI0_D6 */ ++ J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (E33) MCU_OSPI0_D7 */ ++ J784S4_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (C34) MCU_OSPI0_DQS */ ++ >; ++ }; + }; + + &wkup_pmx2 { + bootph-all; ++ pmic_irq_pins_default: pmic-irq-default-pins { ++ pinctrl-single,pins = < ++ /* (AA37) MCU_ADC1_AIN4.WKUP_GPIO0_83 */ ++ J784S4_WKUP_IOPAD(0x0fc, PIN_INPUT, 7) ++ >; ++ }; ++ + wkup_uart0_pins_default: wkup-uart0-default-pins { + bootph-all; + pinctrl-single,pins = < +@@ -238,6 +584,36 @@ + J784S4_WKUP_IOPAD(0x11c, PIN_INPUT, 7) /* (M34) WKUP_GPIO0_67 */ + >; + }; ++ ++ mcu_i2c1_pins_default: mcu-i2c1-default-pins { ++ pinctrl-single,pins = < ++ /* (L35) WKUP_GPIO0_8.MCU_I2C1_SCL */ ++ J784S4_WKUP_IOPAD(0x078, PIN_INPUT_PULLUP, 0) ++ /* (L34) WKUP_GPIO0_9.MCU_I2C1_SDA */ ++ J784S4_WKUP_IOPAD(0x07c, PIN_INPUT_PULLUP, 0) ++ >; ++ }; ++ ++ hdmi_pdn_pins_default: hdmi-pdn-default-pins { ++ pinctrl-single,pins = < ++ J784S4_WKUP_IOPAD(0x090, PIN_INPUT, 7) /* (H37) WKUP_GPIO0_14 */ ++ >; ++ }; ++ ++ mcu_mcan0_pins_default: mcu-mcan0-default-pins { ++ pinctrl-single,pins = < ++ J784S4_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (F38) MCU_MCAN0_RX */ ++ J784S4_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (K33) MCU_MCAN0_TX */ ++ >; ++ }; ++ ++ mcu_mcan1_pins_default: mcu-mcan1-default-pins { ++ pinctrl-single,pins = < ++ J784S4_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (K36) WKUP_GPIO0_5.MCU_MCAN1_RX */ ++ J784S4_WKUP_IOPAD(0x068, PIN_OUTPUT, 0)/* (H35) WKUP_GPIO0_4.MCU_MCAN1_TX */ ++ >; ++ }; ++ + }; + + &wkup_pmx3 { +@@ -248,6 +624,90 @@ + }; + }; + ++&mailbox0_cluster0 { ++ status = "okay"; ++ interrupts = <436>; ++ mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster1 { ++ status = "okay"; ++ interrupts = <432>; ++ mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster2 { ++ status = "okay"; ++ interrupts = <428>; ++ mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster3 { ++ status = "okay"; ++ interrupts = <424>; ++ mbox_main_r5fss2_core0: mbox-main-r5fss2-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_main_r5fss2_core1: mbox-main-r5fss2-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster4 { ++ status = "okay"; ++ interrupts = <420>; ++ mbox_c71_0: mbox-c71-0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_c71_1: mbox-c71-1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster5 { ++ status = "okay"; ++ interrupts = <416>; ++ mbox_c71_2: mbox-c71-2 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_c71_3: mbox-c71-3 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ + &wkup_uart0 { + /* Firmware usage */ + status = "reserved"; +@@ -267,6 +727,93 @@ + compatible = "atmel,24c512"; + reg = <0x51>; + }; ++ ++ tps659413: pmic@48 { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x48>; ++ system-power-controller; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_irq_pins_default>; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <83 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ti,primary-pmic; ++ buck12-supply = <&vsys_3v3>; ++ buck3-supply = <&vsys_3v3>; ++ buck4-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ bucka12: buck12 { ++ regulator-name = "vdd_ddr_1v1"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka3: buck3 { ++ regulator-name = "vdd_ram_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka4: buck4 { ++ regulator-name = "vdd_io_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka5: buck5 { ++ regulator-name = "vdd_mcu_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa1: ldo1 { ++ regulator-name = "vdd_mcuio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa2: ldo2 { ++ regulator-name = "vdd_mcuio_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa3: ldo3 { ++ regulator-name = "vds_dll_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa4: ldo4 { ++ regulator-name = "vda_mcu_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; + }; + + &wkup_gpio0 { +@@ -307,7 +854,7 @@ + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; +- gpio-line-names = "BOARDID_EEPROM_WP", "CAN_STB", "GPIO_uSD_PWR_EN", ++ gpio-line-names = "BOARDID_EEPROM_WP", "CAN_STB", "GPIO_uSD_PWR_EN", + "IO_EXP_MCU_RGMII_RST#", "IO_EXP_PCIe0_4L_PERST#", + "IO_EXP_PCIe1_M.2_RTSz", "IO_EXP_PCIe3_M.2_RTSz", + "PM_INA_BUS_EN", "ENET1_EXP_PWRDN", "EXP1_ENET_RSTz", +@@ -316,6 +863,42 @@ + }; + }; + ++&main_i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c1_pins_default>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ exp2: gpio@21 { ++ compatible = "ti,tca6408"; ++ reg = <0x21>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ gpio-line-names = "CSI_VIO_SEL", "CSI_MUX_SEL_2", "CSI2_RSTz", ++ "IO_EXP_CAM0_GPIO1", "IO_EXP_CAM1_GPIO1"; ++ }; ++ ++ i2c-mux@70 { ++ compatible = "nxp,pca9543"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x70>; ++ ++ cam0_i2c: i2c@0 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0>; ++ }; ++ ++ cam1_i2c: i2c@1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <1>; ++ }; ++ ++ }; ++}; ++ + &main_sdhci0 { + bootph-all; + /* eMMC */ +@@ -362,3 +945,261 @@ + phy-mode = "rgmii-rxid"; + phy-handle = <&mcu_phy0>; + }; ++ ++&mcu_r5fss0_core0 { ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; ++ memory-region = <&mcu_r5fss0_core0_dma_memory_region>, ++ <&mcu_r5fss0_core0_memory_region>; ++}; ++ ++&mcu_r5fss0_core1 { ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; ++ memory-region = <&mcu_r5fss0_core1_dma_memory_region>, ++ <&mcu_r5fss0_core1_memory_region>; ++}; ++ ++&main_r5fss0_core0 { ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; ++ memory-region = <&main_r5fss0_core0_dma_memory_region>, ++ <&main_r5fss0_core0_memory_region>; ++}; ++ ++&main_r5fss0_core1 { ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; ++ memory-region = <&main_r5fss0_core1_dma_memory_region>, ++ <&main_r5fss0_core1_memory_region>; ++}; ++ ++&main_r5fss1_core0 { ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; ++ memory-region = <&main_r5fss1_core0_dma_memory_region>, ++ <&main_r5fss1_core0_memory_region>; ++}; ++ ++&main_r5fss1_core1 { ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; ++ memory-region = <&main_r5fss1_core1_dma_memory_region>, ++ <&main_r5fss1_core1_memory_region>; ++}; ++ ++&main_r5fss2_core0 { ++ mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core0>; ++ memory-region = <&main_r5fss2_core0_dma_memory_region>, ++ <&main_r5fss2_core0_memory_region>; ++}; ++ ++&main_r5fss2_core1 { ++ mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core1>; ++ memory-region = <&main_r5fss2_core1_dma_memory_region>, ++ <&main_r5fss2_core1_memory_region>; ++}; ++ ++&c71_0 { ++ status = "okay"; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_0>; ++ memory-region = <&c71_0_dma_memory_region>, ++ <&c71_0_memory_region>; ++}; ++ ++&c71_1 { ++ status = "okay"; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_1>; ++ memory-region = <&c71_1_dma_memory_region>, ++ <&c71_1_memory_region>; ++}; ++ ++&c71_2 { ++ status = "okay"; ++ mboxes = <&mailbox0_cluster5 &mbox_c71_2>; ++ memory-region = <&c71_2_dma_memory_region>, ++ <&c71_2_memory_region>; ++}; ++ ++&c71_3 { ++ status = "okay"; ++ mboxes = <&mailbox0_cluster5 &mbox_c71_3>; ++ memory-region = <&c71_3_dma_memory_region>, ++ <&c71_3_memory_region>; ++}; ++ ++&wkup_gpio_intr { ++ status = "okay"; ++}; ++ ++&mcu_i2c1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcu_i2c1_pins_default>; ++ clock-frequency = <100000>; ++}; ++ ++&serdes_refclk { ++ status = "okay"; ++ clock-frequency = <100000000>; ++}; ++ ++&dss { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dss_vout0_pins_default>; ++ assigned-clocks = <&k3_clks 218 2>, ++ <&k3_clks 218 5>; ++ assigned-clock-parents = <&k3_clks 218 3>, ++ <&k3_clks 218 7>; ++}; ++ ++&serdes_wiz4 { ++ status = "okay"; ++}; ++ ++&serdes4 { ++ status = "okay"; ++ serdes4_dp_link: phy@0 { ++ reg = <0>; ++ cdns,num-lanes = <4>; ++ #phy-cells = <0>; ++ cdns,phy-type = ; ++ resets = <&serdes_wiz4 1>, <&serdes_wiz4 2>, ++ <&serdes_wiz4 3>, <&serdes_wiz4 4>; ++ }; ++}; ++ ++&mhdp { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dp0_pins_default>; ++ phys = <&serdes4_dp_link>; ++ phy-names = "dpphy"; ++}; ++ ++&dss_ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* DP */ ++ port@0 { ++ reg = <0>; ++ ++ dpi0_out: endpoint { ++ remote-endpoint = <&dp0_in>; ++ }; ++ }; ++ ++ /* HDMI */ ++ port@1 { ++ reg = <1>; ++ ++ dpi1_out0: endpoint { ++ remote-endpoint = <&tfp410_in>; ++ }; ++ }; ++}; ++ ++&dp0_ports { ++ ++ port@0 { ++ reg = <0>; ++ ++ dp0_in: endpoint { ++ remote-endpoint = <&dpi0_out>; ++ }; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ ++ dp0_out: endpoint { ++ remote-endpoint = <&dp0_connector_in>; ++ }; ++ }; ++}; ++ ++&mcu_mcan0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcu_mcan0_pins_default>; ++ phys = <&transceiver1>; ++}; ++ ++&mcu_mcan1 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcu_mcan1_pins_default>; ++ phys = <&transceiver2>; ++}; ++ ++&main_mcan6 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_mcan6_pins_default>; ++ phys = <&transceiver3>; ++}; ++ ++&main_mcan7 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_mcan7_pins_default>; ++ phys = <&transceiver4>; ++}; ++ ++&ospi0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcu_fss0_ospi0_pins_default>; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0x0>; ++ spi-tx-bus-width = <8>; ++ spi-rx-bus-width = <8>; ++ spi-max-frequency = <25000000>; ++ cdns,tshsl-ns = <60>; ++ cdns,tsd2d-ns = <60>; ++ cdns,tchsh-ns = <60>; ++ cdns,tslch-ns = <60>; ++ cdns,read-delay = <4>; ++ ++ partitions { ++ bootph-all; ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "ospi.tiboot3"; ++ reg = <0x0 0x100000>; ++ }; ++ ++ partition@100000 { ++ label = "ospi.tispl"; ++ reg = <0x100000 0x200000>; ++ }; ++ ++ partition@300000 { ++ label = "ospi.u-boot"; ++ reg = <0x300000 0x400000>; ++ }; ++ ++ partition@700000 { ++ label = "ospi.env"; ++ reg = <0x700000 0x40000>; ++ }; ++ ++ partition@740000 { ++ label = "ospi.env.backup"; ++ reg = <0x740000 0x40000>; ++ }; ++ ++ partition@800000 { ++ label = "ospi.rootfs"; ++ reg = <0x800000 0x37c0000>; ++ }; ++ ++ partition@3fc0000 { ++ bootph-pre-ram; ++ label = "ospi.phypattern"; ++ reg = <0x3fc0000 0x40000>; ++ }; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts +--- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -91,24 +91,25 @@ + }; + + &wkup_pmx0 { ++}; ++ ++&wkup_pmx2 { + mcu_uart0_pins_default: mcu-uart0-default-pins { + pinctrl-single,pins = < +- J721E_WKUP_IOPAD(0xf4, PIN_INPUT, 0) /* (D20) MCU_UART0_RXD */ +- J721E_WKUP_IOPAD(0xf0, PIN_OUTPUT, 0) /* (D19) MCU_UART0_TXD */ +- J721E_WKUP_IOPAD(0xf8, PIN_INPUT, 0) /* (E20) MCU_UART0_CTSn */ +- J721E_WKUP_IOPAD(0xfc, PIN_OUTPUT, 0) /* (E21) MCU_UART0_RTSn */ ++ J721E_WKUP_IOPAD(0x90, PIN_INPUT, 0) /* (E20) MCU_UART0_CTSn */ ++ J721E_WKUP_IOPAD(0x94, PIN_OUTPUT, 0) /* (E21) MCU_UART0_RTSn */ ++ J721E_WKUP_IOPAD(0x8c, PIN_INPUT, 0) /* (D20) MCU_UART0_RXD */ ++ J721E_WKUP_IOPAD(0x88, PIN_OUTPUT, 0) /* (D19) MCU_UART0_TXD */ + >; + }; + + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < +- J721E_WKUP_IOPAD(0xb0, PIN_INPUT, 0) /* (B14) WKUP_UART0_RXD */ +- J721E_WKUP_IOPAD(0xb4, PIN_OUTPUT, 0) /* (A14) WKUP_UART0_TXD */ ++ J721E_WKUP_IOPAD(0x48, PIN_INPUT, 0) /* (B14) WKUP_UART0_RXD */ ++ J721E_WKUP_IOPAD(0x4c, PIN_OUTPUT, 0) /* (A14) WKUP_UART0_TXD */ + >; + }; +-}; + +-&wkup_pmx2 { + mcu_cpsw_pins_default: mcu-cpsw-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */ +@@ -210,7 +211,6 @@ + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mcu_uart0_pins_default>; +- clock-frequency = <96000000>; + }; + + &main_uart0 { +@@ -382,15 +382,9 @@ + }; + + &pcie1_rc { ++ status = "okay"; + reset-gpios = <&exp1 2 GPIO_ACTIVE_HIGH>; + phys = <&serdes0_pcie_link>; + phy-names = "pcie-phy"; + num-lanes = <2>; + }; +- +-&pcie1_ep { +- phys = <&serdes0_pcie_link>; +- phy-names = "pcie-phy"; +- num-lanes = <2>; +- status = "disabled"; +-}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -33,10 +33,11 @@ + ranges = <0x00 0x00 0x00100000 0x1c000>; + + serdes_ln_ctrl: mux-controller@4080 { +- compatible = "mmio-mux"; ++ compatible = "reg-mux"; ++ reg = <0x4080 0x20>; + #mux-control-cells = <1>; +- mux-reg-masks = <0x4080 0x3>, <0x4084 0x3>, /* SERDES0 lane0/1 select */ +- <0x4088 0x3>, <0x408c 0x3>; /* SERDES0 lane2/3 select */ ++ mux-reg-masks = <0x0 0x3>, <0x4 0x3>, /* SERDES0 lane0/1 select */ ++ <0x8 0x3>, <0xc 0x3>; /* SERDES0 lane2/3 select */ + }; + + cpsw0_phy_gmii_sel: phy@4044 { +@@ -47,9 +48,10 @@ + }; + + usb_serdes_mux: mux-controller@4000 { +- compatible = "mmio-mux"; ++ compatible = "reg-mux"; ++ reg = <0x4000 0x4>; + #mux-control-cells = <1>; +- mux-reg-masks = <0x4000 0x8000000>; /* USB0 to SERDES0 lane 1/3 mux */ ++ mux-reg-masks = <0x0 0x8000000>; /* USB0 to SERDES0 lane 1/3 mux */ + }; + }; + +@@ -91,7 +93,7 @@ + }; + + main_navss: bus@30000000 { +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>; +@@ -281,8 +283,12 @@ + compatible = "ti,j721e-navss-main-udmap"; + reg = <0x00 0x31150000 0x00 0x100>, + <0x00 0x34000000 0x00 0x100000>, +- <0x00 0x35000000 0x00 0x100000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x00 0x35000000 0x00 0x100000>, ++ <0x00 0x30b00000 0x00 0x4000>, ++ <0x00 0x30c00000 0x00 0x4000>, ++ <0x00 0x30d00000 0x00 0x4000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&main_udmass_inta>; + #dma-cells = <1>; + +@@ -395,7 +401,7 @@ + + /* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */ + main_timerio_input: pinctrl@104200 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + reg = <0x0 0x104200 0x0 0x50>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; +@@ -404,7 +410,7 @@ + + /* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */ + main_timerio_output: pinctrl@104280 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + reg = <0x0 0x104280 0x0 0x20>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; +@@ -412,7 +418,7 @@ + }; + + main_pmx0: pinctrl@11c000 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x11c000 0x00 0x10c>; + #pinctrl-cells = <1>; +@@ -421,7 +427,7 @@ + }; + + main_pmx1: pinctrl@11c11c { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x11c11c 0x00 0xc>; + #pinctrl-cells = <1>; +@@ -647,6 +653,7 @@ + ti,otap-del-sel-hs400 = <0x5>; + ti,itap-del-sel-legacy = <0x10>; + ti,itap-del-sel-mmc-hs = <0xa>; ++ ti,itap-del-sel-ddr52 = <0x3>; + ti,strobe-sel = <0x77>; + ti,clkbuf-sel = <0x7>; + ti,trm-icp = <0x8>; +@@ -765,26 +772,7 @@ + ranges = <0x01000000 0x0 0x18001000 0x00 0x18001000 0x0 0x0010000>, + <0x02000000 0x0 0x18011000 0x00 0x18011000 0x0 0x7fef000>; + dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>; +- }; +- +- pcie1_ep: pcie-ep@2910000 { +- compatible = "ti,j7200-pcie-ep", "ti,j721e-pcie-ep"; +- reg = <0x00 0x02910000 0x00 0x1000>, +- <0x00 0x02917000 0x00 0x400>, +- <0x00 0x0d800000 0x00 0x00800000>, +- <0x00 0x18000000 0x00 0x08000000>; +- reg-names = "intd_cfg", "user_cfg", "reg", "mem"; +- interrupt-names = "link_state"; +- interrupts = ; +- ti,syscon-pcie-ctrl = <&scm_conf 0x4074>; +- max-link-speed = <3>; +- num-lanes = <4>; +- power-domains = <&k3_pds 240 TI_SCI_PD_EXCLUSIVE>; +- clocks = <&k3_clks 240 6>; +- clock-names = "fck"; +- max-functions = /bits/ 8 <6>; +- max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; +- dma-coherent; ++ status = "disabled"; + }; + + usbss0: cdns-usb@4104000 { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -178,14 +178,21 @@ + }; + }; + +- chipid@43000014 { +- compatible = "ti,am654-chipid"; +- reg = <0x00 0x43000014 0x00 0x4>; ++ wkup_conf: bus@43000000 { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x00 0x43000000 0x20000>; ++ ++ chipid: chipid@14 { ++ compatible = "ti,am654-chipid"; ++ reg = <0x14 0x4>; ++ }; + }; + + /* MCU_TIMERIO pad input CTRLMMR_MCU_TIMER*_CTRL registers */ + mcu_timerio_input: pinctrl@40f04200 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + reg = <0x0 0x40f04200 0x0 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; +@@ -195,7 +202,7 @@ + + /* MCU_TIMERIO pad output CTRLMMR_MCU_TIMERIO*_CTRL registers */ + mcu_timerio_output: pinctrl@40f04280 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + reg = <0x0 0x40f04280 0x0 0x28>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; +@@ -204,7 +211,7 @@ + }; + + wkup_pmx0: pinctrl@4301c000 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c000 0x00 0x34>; + #pinctrl-cells = <1>; +@@ -213,7 +220,7 @@ + }; + + wkup_pmx1: pinctrl@4301c038 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c038 0x00 0x8>; + #pinctrl-cells = <1>; +@@ -222,7 +229,7 @@ + }; + + wkup_pmx2: pinctrl@4301c068 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c068 0x00 0xec>; + #pinctrl-cells = <1>; +@@ -231,7 +238,7 @@ + }; + + wkup_pmx3: pinctrl@4301c174 { +- compatible = "pinctrl-single"; ++ compatible = "ti,j7200-padconf", "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c174 0x00 0x20>; + #pinctrl-cells = <1>; +@@ -318,7 +325,7 @@ + }; + + mcu_navss: bus@28380000 { +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>; +@@ -346,8 +353,12 @@ + compatible = "ti,j721e-navss-mcu-udmap"; + reg = <0x00 0x285c0000 0x00 0x100>, + <0x00 0x2a800000 0x00 0x40000>, +- <0x00 0x2aa00000 0x00 0x40000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x00 0x2aa00000 0x00 0x40000>, ++ <0x00 0x284a0000 0x00 0x4000>, ++ <0x00 0x284c0000 0x00 0x4000>, ++ <0x00 0x28400000 0x00 0x2000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&main_udmass_inta>; + #dma-cells = <1>; + +@@ -507,17 +518,18 @@ + status = "disabled"; + }; + +- fss: syscon@47000000 { +- compatible = "syscon", "simple-mfd"; ++ fss: bus@47000000 { ++ compatible = "simple-bus"; + reg = <0x00 0x47000000 0x00 0x100>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + +- hbmc_mux: hbmc-mux { +- compatible = "mmio-mux"; ++ hbmc_mux: mux-controller@47000004 { ++ compatible = "reg-mux"; ++ reg = <0x00 0x47000004 0x00 0x4>; + #mux-control-cells = <1>; +- mux-reg-masks = <0x4 0x2>; /* HBMC select */ ++ mux-reg-masks = <0x0 0x2>; /* HBMC select */ + }; + + hbmc: hyperbus@47034000 { +@@ -637,4 +649,11 @@ + power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>; + #thermal-sensor-cells = <1>; + }; ++ ++ mcu_esm: esm@40800000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x40800000 0x00 0x1000>; ++ ti,esm-pins = <95>; ++ bootph-pre-ram; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -127,6 +127,14 @@ + }; + }; + ++&wkup_pmx3 { ++ pmic_irq_pins_default: pmic-irq-default-pins { ++ pinctrl-single,pins = < ++ J721E_WKUP_IOPAD(0x01c, PIN_INPUT, 7) /* (E18) WKUP_GPIO0_84 */ ++ >; ++ }; ++}; ++ + &main_pmx0 { + main_i2c0_pins_default: main-i2c0-default-pins { + pinctrl-single,pins = < +@@ -214,25 +222,25 @@ + }; + + &mcu_r5fss0_core0 { +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + memory-region = <&mcu_r5fss0_core0_dma_memory_region>, + <&mcu_r5fss0_core0_memory_region>; + }; + + &mcu_r5fss0_core1 { +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + memory-region = <&mcu_r5fss0_core1_dma_memory_region>, + <&mcu_r5fss0_core1_memory_region>; + }; + + &main_r5fss0_core0 { +- mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + memory-region = <&main_r5fss0_core0_dma_memory_region>, + <&main_r5fss0_core0_memory_region>; + }; + + &main_r5fss0_core1 { +- mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + memory-region = <&main_r5fss0_core1_dma_memory_region>, + <&main_r5fss0_core1_memory_region>; + }; +@@ -264,6 +272,151 @@ + compatible = "atmel,24c256"; + reg = <0x50>; + }; ++ ++ tps659414: pmic@48 { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x48>; ++ system-power-controller; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_irq_pins_default>; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <84 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ti,primary-pmic; ++ buck1-supply = <&vsys_3v3>; ++ buck2-supply = <&vsys_3v3>; ++ buck3-supply = <&vsys_3v3>; ++ buck4-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ bucka1: buck1 { ++ regulator-name = "vda_mcu_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka2: buck2 { ++ regulator-name = "vdd_mcuio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka3: buck3 { ++ regulator-name = "vdd_mcu_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka4: buck4 { ++ regulator-name = "vdd_ddr_1v1"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka5: buck5 { ++ regulator-name = "vdd_phyio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa1: ldo1 { ++ regulator-name = "vdd1_lpddr4_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa2: ldo2 { ++ regulator-name = "vda_dll_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa3: ldo3 { ++ regulator-name = "vdd_wk_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa4: ldo4 { ++ regulator-name = "vda_pll_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ lp876441: pmic@4c { ++ compatible = "ti,lp8764-q1"; ++ reg = <0x4c>; ++ system-power-controller; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <84 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ buck1-supply = <&vsys_3v3>; ++ buck2-supply = <&vsys_3v3>; ++ buck3-supply = <&vsys_3v3>; ++ buck4-supply = <&vsys_3v3>; ++ ++ regulators: regulators { ++ buckb1: buck1 { ++ regulator-name = "vdd_cpu_avs"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <900000>; ++ regulator-always-on; ++ regulator-boot-on; ++ bootph-pre-ram; ++ }; ++ ++ buckb2: buck2 { ++ regulator-name = "vdd_ram_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buckb3: buck3 { ++ regulator-name = "vdd_core_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buckb4: buck4 { ++ regulator-name = "vdd_io_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; + }; + + &ospi0 { +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts +--- a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -1,9 +1,9 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * https://beagleboard.org/ai-64 +- * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ +- * Copyright (C) 2022 Jason Kridner, BeagleBoard.org Foundation +- * Copyright (C) 2022 Robert Nelson, BeagleBoard.org Foundation ++ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2022-2024 Jason Kridner, BeagleBoard.org Foundation ++ * Copyright (C) 2022-2024 Robert Nelson, BeagleBoard.org Foundation + */ + + /dts-v1/; +@@ -32,6 +32,8 @@ + + chosen { + stdout-path = "serial2:115200n8"; ++ base_dtb = "k3-j721e-beagleboneai64.dts"; ++ base_dtb_timestamp = __TIMESTAMP__; + }; + + memory@80000000 { +@@ -190,32 +192,38 @@ + pinctrl-0 = <&led_pins_default>; + + led-0 { ++ label = "beaglebone:green:usr0"; + gpios = <&main_gpio0 96 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_HEARTBEAT; + linux,default-trigger = "heartbeat"; + }; + + led-1 { ++ label = "beaglebone:green:usr1"; + gpios = <&main_gpio0 95 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_DISK_ACTIVITY; + linux,default-trigger = "mmc0"; + }; + + led-2 { ++ label = "beaglebone:green:usr2"; + gpios = <&main_gpio0 97 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_CPU; + linux,default-trigger = "cpu"; + }; + + led-3 { ++ label = "beaglebone:green:usr3"; + gpios = <&main_gpio0 110 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_DISK_ACTIVITY; + linux,default-trigger = "mmc1"; + }; + + led-4 { ++ label = "beaglebone:green:usr4"; + gpios = <&main_gpio0 109 GPIO_ACTIVE_HIGH>; + function = LED_FUNCTION_WLAN; ++ linux,default-trigger = "phy0tx"; + default-state = "off"; + }; + }; +@@ -936,58 +944,58 @@ + }; + + &mcu_r5fss0_core0 { +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + memory-region = <&mcu_r5fss0_core0_dma_memory_region>, + <&mcu_r5fss0_core0_memory_region>; + }; + + &mcu_r5fss0_core1 { +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + memory-region = <&mcu_r5fss0_core1_dma_memory_region>, + <&mcu_r5fss0_core1_memory_region>; + }; + + &main_r5fss0_core0 { +- mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + memory-region = <&main_r5fss0_core0_dma_memory_region>, + <&main_r5fss0_core0_memory_region>; + }; + + &main_r5fss0_core1 { +- mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + memory-region = <&main_r5fss0_core1_dma_memory_region>, + <&main_r5fss0_core1_memory_region>; + }; + + &main_r5fss1_core0 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; + memory-region = <&main_r5fss1_core0_dma_memory_region>, + <&main_r5fss1_core0_memory_region>; + }; + + &main_r5fss1_core1 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; + memory-region = <&main_r5fss1_core1_dma_memory_region>, + <&main_r5fss1_core1_memory_region>; + }; + + &c66_0 { + status = "okay"; +- mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>; ++ mboxes = <&mailbox0_cluster3 &mbox_c66_0>; + memory-region = <&c66_0_dma_memory_region>, + <&c66_0_memory_region>; + }; + + &c66_1 { + status = "okay"; +- mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>; ++ mboxes = <&mailbox0_cluster3 &mbox_c66_1>; + memory-region = <&c66_1_dma_memory_region>, + <&c66_1_memory_region>; + }; + + &c71_0 { + status = "okay"; +- mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_0>; + memory-region = <&c71_0_dma_memory_region>, + <&c71_0_memory_region>; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts +--- a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -1,6 +1,6 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* +- * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2019-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + * Product Link: https://www.ti.com/tool/J721EXCPXEVM + */ +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e.dtsi b/arch/arm64/boot/dts/ti/k3-j721e.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j721e.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for J721E SoC Family + * +- * Copyright (C) 2016-2019 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2016-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #include +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-evm-pcie0-ep.dtso b/arch/arm64/boot/dts/ti/k3-j721e-evm-pcie0-ep.dtso +--- a/arch/arm64/boot/dts/ti/k3-j721e-evm-pcie0-ep.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-evm-pcie0-ep.dtso 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,53 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * DT Overlay for enabling PCIE0 instance in Endpoint Configuration with the ++ * J7 common processor board. ++ * ++ * J7 Common Processor Board Product Link: https://www.ti.com/tool/J721EXCPXEVM ++ * ++ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++#include "k3-pinctrl.h" ++ ++/* ++ * Since Root Complex and Endpoint modes are mutually exclusive ++ * disable Root Complex mode. ++ */ ++&pcie0_rc { ++ status = "disabled"; ++}; ++ ++&cbass_main { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&gic500>; ++ ++ pcie0_ep: pcie-ep@2900000 { ++ compatible = "ti,j721e-pcie-ep"; ++ reg = <0x00 0x02900000 0x00 0x1000>, ++ <0x00 0x02907000 0x00 0x400>, ++ <0x00 0x0d000000 0x00 0x00800000>, ++ <0x00 0x10000000 0x00 0x08000000>; ++ reg-names = "intd_cfg", "user_cfg", "reg", "mem"; ++ interrupt-names = "link_state"; ++ interrupts = ; ++ ti,syscon-pcie-ctrl = <&scm_conf 0x4070>; ++ max-link-speed = <3>; ++ num-lanes = <1>; ++ power-domains = <&k3_pds 239 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 239 1>; ++ clock-names = "fck"; ++ max-functions = /bits/ 8 <6>; ++ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; ++ dma-coherent; ++ phys = <&serdes0_pcie_link>; ++ phy-names = "pcie-phy"; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for J721E SoC Family Main Domain peripherals + * +- * Copyright (C) 2016-2020 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2016-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + #include + #include +@@ -45,15 +45,15 @@ + ranges = <0x0 0x0 0x00100000 0x1c000>; + + serdes_ln_ctrl: mux-controller@4080 { +- compatible = "mmio-mux"; +- reg = <0x00004080 0x50>; ++ compatible = "reg-mux"; ++ reg = <0x4080 0x50>; + #mux-control-cells = <1>; +- mux-reg-masks = <0x4080 0x3>, <0x4084 0x3>, /* SERDES0 lane0/1 select */ +- <0x4090 0x3>, <0x4094 0x3>, /* SERDES1 lane0/1 select */ +- <0x40a0 0x3>, <0x40a4 0x3>, /* SERDES2 lane0/1 select */ +- <0x40b0 0x3>, <0x40b4 0x3>, /* SERDES3 lane0/1 select */ +- <0x40c0 0x3>, <0x40c4 0x3>, <0x40c8 0x3>, <0x40cc 0x3>; +- /* SERDES4 lane0/1/2/3 select */ ++ mux-reg-masks = <0x0 0x3>, <0x4 0x3>, /* SERDES0 lane0/1 select */ ++ <0x10 0x3>, <0x14 0x3>, /* SERDES1 lane0/1 select */ ++ <0x20 0x3>, <0x24 0x3>, /* SERDES2 lane0/1 select */ ++ <0x30 0x3>, <0x34 0x3>, /* SERDES3 lane0/1 select */ ++ <0x40 0x3>, <0x44 0x3>, /* SERDES4 lane0/1 select */ ++ <0x48 0x3>, <0x4c 0x3>; /* SERDES4 lane2/3 select */ + idle-states = , , + , , + , , +@@ -70,10 +70,11 @@ + }; + + usb_serdes_mux: mux-controller@4000 { +- compatible = "mmio-mux"; ++ compatible = "reg-mux"; ++ reg = <0x4000 0x20>; + #mux-control-cells = <1>; +- mux-reg-masks = <0x4000 0x8000000>, /* USB0 to SERDES0/3 mux */ +- <0x4010 0x8000000>; /* USB1 to SERDES1/2 mux */ ++ mux-reg-masks = <0x0 0x8000000>, /* USB0 to SERDES0/3 mux */ ++ <0x10 0x8000000>; /* USB1 to SERDES1/2 mux */ + }; + + ehrpwm_tbclk: clock-controller@4140 { +@@ -181,7 +182,7 @@ + }; + + main_navss: bus@30000000 { +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>; +@@ -382,8 +383,12 @@ + compatible = "ti,j721e-navss-main-udmap"; + reg = <0x0 0x31150000 0x0 0x100>, + <0x0 0x34000000 0x0 0x100000>, +- <0x0 0x35000000 0x0 0x100000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x0 0x35000000 0x0 0x100000>, ++ <0x0 0x30b00000 0x0 0x20000>, ++ <0x0 0x30c00000 0x0 0x10000>, ++ <0x0 0x30d00000 0x0 0x8000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&main_udmass_inta>; + #dma-cells = <1>; + +@@ -568,6 +573,128 @@ + pinctrl-single,function-mask = <0x0000001f>; + }; + ++ ti_csi2rx0: ticsi2rx@4500000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ reg = <0x0 0x4500000 0x0 0x1000>; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dmas = <&main_udmap 0x4940>; ++ dma-names = "rx0"; ++ power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ cdns_csi2rx0: csi-bridge@4504000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x0 0x4504000 0x0 0x1000>; ++ clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>, ++ <&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy0>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi0_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi0_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi0_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi0_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ ti_csi2rx1: ticsi2rx@4510000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ reg = <0x0 0x4510000 0x0 0x1000>; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dmas = <&main_udmap 0x4960>; ++ dma-names = "rx0"; ++ power-domains = <&k3_pds 27 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ cdns_csi2rx1: csi-bridge@4514000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x0 0x4514000 0x0 0x1000>; ++ clocks = <&k3_clks 27 2>, <&k3_clks 27 0>, <&k3_clks 27 2>, ++ <&k3_clks 27 2>, <&k3_clks 27 3>, <&k3_clks 27 3>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy1>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi1_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi1_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi1_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi1_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi1_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ dphy0: phy@4580000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x0 0x4580000 0x0 0x1100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ dphy1: phy@4590000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x0 0x4590000 0x0 0x1100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ + serdes_wiz0: wiz@5000000 { + compatible = "ti,j721e-wiz-16g"; + #address-cells = <1>; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for J721E SoC Family MCU/WAKEUP Domain peripherals + * +- * Copyright (C) 2016-2020 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2016-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + &cbass_mcu_wakeup { +@@ -48,9 +48,16 @@ + }; + }; + +- chipid@43000014 { +- compatible = "ti,am654-chipid"; +- reg = <0x0 0x43000014 0x0 0x4>; ++ wkup_conf: bus@43000000 { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x00 0x43000000 0x20000>; ++ ++ chipid: chipid@14 { ++ compatible = "ti,am654-chipid"; ++ reg = <0x14 0x4>; ++ }; + }; + + wkup_pmx0: pinctrl@4301c000 { +@@ -346,9 +353,9 @@ + + hbmc_mux: mux-controller@47000004 { + compatible = "reg-mux"; +- reg = <0x00 0x47000004 0x00 0x2>; ++ reg = <0x00 0x47000004 0x00 0x4>; + #mux-control-cells = <1>; +- mux-reg-masks = <0x4 0x2>; /* HBMC select */ ++ mux-reg-masks = <0x0 0x2>; /* HBMC select */ + }; + + hbmc: hyperbus@47034000 { +@@ -440,7 +447,7 @@ + }; + + mcu_navss: bus@28380000 { +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>; +@@ -468,8 +475,12 @@ + compatible = "ti,j721e-navss-mcu-udmap"; + reg = <0x0 0x285c0000 0x0 0x100>, + <0x0 0x2a800000 0x0 0x40000>, +- <0x0 0x2aa00000 0x0 0x40000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x0 0x2aa00000 0x0 0x40000>, ++ <0x0 0x284a0000 0x0 0x4000>, ++ <0x0 0x284c0000 0x0 0x4000>, ++ <0x0 0x28400000 0x0 0x2000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&main_udmass_inta>; + #dma-cells = <1>; + +@@ -671,4 +682,11 @@ + power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>; + #thermal-sensor-cells = <1>; + }; ++ ++ mcu_esm: esm@40800000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x40800000 0x00 0x1000>; ++ ti,esm-pins = <95>; ++ bootph-pre-ram; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-dual-imx219.dtso b/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-dual-imx219.dtso +--- a/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-dual-imx219.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-dual-imx219.dtso 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,165 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/** ++ * DT Overlay for dual RPi Camera V2.1 (Sony IMX219) interfaced with CSI2 ++ * on J721E SK, AM68 SK or AM69-SK board. ++ * https://datasheets.raspberrypi.org/camera/camera-v2-schematic.pdf ++ * ++ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include "k3-pinctrl.h" ++ ++&{/} { ++ clk_imx219_fixed: imx219-xclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <24000000>; ++ }; ++}; ++ ++&csi_mux { ++ idle-state = <1>; ++}; ++ ++/* CAM0 I2C */ ++&cam0_i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ imx219_0: imx219-0@10 { ++ compatible = "sony,imx219"; ++ reg = <0x10>; ++ ++ clocks = <&clk_imx219_fixed>; ++ clock-names = "xclk"; ++ ++ port { ++ csi2_cam0: endpoint { ++ remote-endpoint = <&csi2rx0_in_sensor>; ++ link-frequencies = /bits/ 64 <456000000>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++/* CAM1 I2C */ ++&cam1_i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ imx219_1: imx219-1@10 { ++ compatible = "sony,imx219"; ++ reg = <0x10>; ++ ++ clocks = <&clk_imx219_fixed>; ++ clock-names = "xclk"; ++ ++ port { ++ csi2_cam1: endpoint { ++ remote-endpoint = <&csi2rx1_in_sensor>; ++ link-frequencies = /bits/ 64 <456000000>; ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++}; ++ ++ ++&cdns_csi2rx0 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "okay"; ++ ++ csi2rx0_in_sensor: endpoint { ++ remote-endpoint = <&csi2_cam0>; ++ bus-type = <4>; /* CSI2 DPHY. */ ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ ++ csi0_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi0_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi0_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi0_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++}; ++ ++&dphy0 { ++ status = "okay"; ++}; ++ ++&ti_csi2rx0 { ++ status = "okay"; ++}; ++ ++&cdns_csi2rx1 { ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi1_port0: port@0 { ++ reg = <0>; ++ status = "okay"; ++ ++ csi2rx1_in_sensor: endpoint { ++ remote-endpoint = <&csi2_cam1>; ++ bus-type = <4>; /* CSI2 DPHY. */ ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ ++ csi1_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi1_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi1_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi1_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++}; ++ ++&dphy1 { ++ status = "okay"; ++}; ++ ++&ti_csi2rx1 { ++ status = "okay"; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts +--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -1,6 +1,6 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* +- * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2021-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + * J721E SK URL: https://www.ti.com/tool/SK-TDA4VM + */ +@@ -286,6 +286,15 @@ + }; + }; + }; ++ ++ csi_mux: mux-controller { ++ compatible = "gpio-mux"; ++ #mux-state-cells = <1>; ++ mux-gpios = <&main_gpio0 88 GPIO_ACTIVE_HIGH>; ++ idle-state = <0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_csi_mux_sel_pins_default>; ++ }; + }; + + &main_pmx0 { +@@ -352,6 +361,12 @@ + >; + }; + ++ main_csi_mux_sel_pins_default: main-csi-mux-sel-default-pins { ++ pinctrl-single,pins = < ++ J721E_IOPAD(0x164, PIN_OUTPUT, 7) /* (V29) RGMII5_TD2 */ ++ >; ++ }; ++ + dp0_pins_default: dp0-default-pins { + pinctrl-single,pins = < + J721E_IOPAD(0x1c4, PIN_INPUT, 5) /* SPI0_CS1.DP0_HPD */ +@@ -459,6 +474,12 @@ + }; + + &wkup_pmx0 { ++ pmic_irq_pins_default: pmic-irq-default-pins { ++ pinctrl-single,pins = < ++ J721E_WKUP_IOPAD(0x0cc, PIN_INPUT, 7) /* (G28) WKUP_GPIO0_7 */ ++ >; ++ }; ++ + mcu_cpsw_pins_default: mcu-cpsw-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0x84, PIN_INPUT, 0) /* (B24) MCU_RGMII1_RD0 */ +@@ -560,6 +581,151 @@ + compatible = "atmel,24c512"; + reg = <0x51>; + }; ++ ++ tps659413: pmic@48 { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x48>; ++ system-power-controller; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_irq_pins_default>; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <7 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ti,primary-pmic; ++ buck123-supply = <&vsys_3v3>; ++ buck4-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ bucka123: buck123 { ++ regulator-name = "vdd_cpu_avs"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ bootph-pre-ram; ++ }; ++ ++ bucka4: buck4 { ++ regulator-name = "vdd_mcu_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka5: buck5 { ++ regulator-name = "vdd_phyio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa1: ldo1 { ++ regulator-name = "vdd1_lpddr4_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa2: ldo2 { ++ regulator-name = "vdd_mcuio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa3: ldo3 { ++ regulator-name = "vdda_dll_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa4: ldo4 { ++ regulator-name = "vda_mcu_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ tps659411: pmic@4c { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x4c>; ++ system-power-controller; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <7 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ buck1234-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ buckb1234: buck1234 { ++ regulator-name = "vdd_core_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buckb5: buck5 { ++ regulator-name = "vdd_ram_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob1: ldo1 { ++ regulator-name = "vdd_sd_dv"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob2: ldo2 { ++ regulator-name = "vdd_usb_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob3: ldo3 { ++ regulator-name = "vdd_io_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob4: ldo4 { ++ regulator-name = "vda_pll_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; + }; + + &mcu_uart0 { +@@ -707,14 +873,14 @@ + reg = <0x70>; + + /* CSI0 I2C */ +- i2c@0 { ++ cam0_i2c: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + /* CSI1 I2C */ +- i2c@1 { ++ cam1_i2c: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; +@@ -1017,58 +1183,58 @@ + }; + + &mcu_r5fss0_core0 { +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + memory-region = <&mcu_r5fss0_core0_dma_memory_region>, + <&mcu_r5fss0_core0_memory_region>; + }; + + &mcu_r5fss0_core1 { +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + memory-region = <&mcu_r5fss0_core1_dma_memory_region>, + <&mcu_r5fss0_core1_memory_region>; + }; + + &main_r5fss0_core0 { +- mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + memory-region = <&main_r5fss0_core0_dma_memory_region>, + <&main_r5fss0_core0_memory_region>; + }; + + &main_r5fss0_core1 { +- mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + memory-region = <&main_r5fss0_core1_dma_memory_region>, + <&main_r5fss0_core1_memory_region>; + }; + + &main_r5fss1_core0 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; + memory-region = <&main_r5fss1_core0_dma_memory_region>, + <&main_r5fss1_core0_memory_region>; + }; + + &main_r5fss1_core1 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; + memory-region = <&main_r5fss1_core1_dma_memory_region>, + <&main_r5fss1_core1_memory_region>; + }; + + &c66_0 { + status = "okay"; +- mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>; ++ mboxes = <&mailbox0_cluster3 &mbox_c66_0>; + memory-region = <&c66_0_dma_memory_region>, + <&c66_0_memory_region>; + }; + + &c66_1 { + status = "okay"; +- mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>; ++ mboxes = <&mailbox0_cluster3 &mbox_c66_1>; + memory-region = <&c66_1_dma_memory_region>, + <&c66_1_memory_region>; + }; + + &c71_0 { + status = "okay"; +- mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_0>; + memory-region = <&c71_0_dma_memory_region>, + <&c71_0_memory_region>; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,6 +1,6 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* +- * Copyright (C) 2019-2020 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2019-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + * Product Link: https://www.ti.com/tool/J721EXSOMXEVM + */ +@@ -152,6 +152,12 @@ + >; + }; + ++ pmic_irq_pins_default: pmic-irq-default-pins { ++ pinctrl-single,pins = < ++ J721E_WKUP_IOPAD(0x0d4, PIN_INPUT, 7) /* (G26) WKUP_GPIO0_9 */ ++ >; ++ }; ++ + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { + pinctrl-single,pins = < + J721E_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* MCU_OSPI0_CLK */ +@@ -199,6 +205,160 @@ + compatible = "atmel,24c256"; + reg = <0x50>; + }; ++ ++ tps659413: pmic@48 { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x48>; ++ system-power-controller; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_irq_pins_default>; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <9 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ti,primary-pmic; ++ buck12-supply = <&vsys_3v3>; ++ buck3-supply = <&vsys_3v3>; ++ buck4-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ bucka12: buck12 { ++ regulator-name = "vdd_cpu_avs"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ bootph-pre-ram; ++ }; ++ ++ bucka3: buck3 { ++ regulator-name = "vdd_mcu_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka4: buck4 { ++ regulator-name = "vdd_ddr_1v1"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka5: buck5 { ++ regulator-name = "vdd_phyio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa1: ldo1 { ++ regulator-name = "vdd1_lpddr4_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa2: ldo2 { ++ regulator-name = "vdd_mcuio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa3: ldo3 { ++ regulator-name = "vdda_dll_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa4: ldo4 { ++ regulator-name = "vda_mcu_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ tps659411: pmic@4c { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x4c>; ++ system-power-controller; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <9 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ buck1234-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ buckb1234: buck1234 { ++ regulator-name = "vdd_core_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buckb5: buck5 { ++ regulator-name = "vdd_ram_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob1: ldo1 { ++ regulator-name = "vdd_sd_dv"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob2: ldo2 { ++ regulator-name = "vdd_usb_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob3: ldo3 { ++ regulator-name = "vdd_io_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob4: ldo4 { ++ regulator-name = "vda_pll_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; + }; + + &ospi0 { +@@ -389,58 +549,58 @@ + }; + + &mcu_r5fss0_core0 { +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; + memory-region = <&mcu_r5fss0_core0_dma_memory_region>, + <&mcu_r5fss0_core0_memory_region>; + }; + + &mcu_r5fss0_core1 { +- mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; + memory-region = <&mcu_r5fss0_core1_dma_memory_region>, + <&mcu_r5fss0_core1_memory_region>; + }; + + &main_r5fss0_core0 { +- mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>; ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; + memory-region = <&main_r5fss0_core0_dma_memory_region>, + <&main_r5fss0_core0_memory_region>; + }; + + &main_r5fss0_core1 { +- mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>; ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; + memory-region = <&main_r5fss0_core1_dma_memory_region>, + <&main_r5fss0_core1_memory_region>; + }; + + &main_r5fss1_core0 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; + memory-region = <&main_r5fss1_core0_dma_memory_region>, + <&main_r5fss1_core0_memory_region>; + }; + + &main_r5fss1_core1 { +- mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>; ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; + memory-region = <&main_r5fss1_core1_dma_memory_region>, + <&main_r5fss1_core1_memory_region>; + }; + + &c66_0 { + status = "okay"; +- mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>; ++ mboxes = <&mailbox0_cluster3 &mbox_c66_0>; + memory-region = <&c66_0_dma_memory_region>, + <&c66_0_memory_region>; + }; + + &c66_1 { + status = "okay"; +- mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>; ++ mboxes = <&mailbox0_cluster3 &mbox_c66_1>; + memory-region = <&c66_1_dma_memory_region>, + <&c66_1_memory_region>; + }; + + &c71_0 { + status = "okay"; +- mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_0>; + memory-region = <&c71_0_dma_memory_region>, + <&c71_0_memory_region>; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,4 +1,7 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/* ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ ++ */ + + #include + +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts +--- a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -147,6 +147,13 @@ + >; + }; + ++ main_i2c5_pins_default: main-i2c5-default-pins { ++ pinctrl-single,pins = < ++ J721S2_IOPAD(0x01c, PIN_INPUT, 8) /* (Y24) MCAN15_TX.I2C5_SCL */ ++ J721S2_IOPAD(0x018, PIN_INPUT, 8) /* (W23) MCAN14_RX.I2C5_SDA */ ++ >; ++ }; ++ + main_mmc1_pins_default: main-mmc1-default-pins { + pinctrl-single,pins = < + J721S2_IOPAD(0x104, PIN_INPUT, 0) /* (P23) MMC1_CLK */ +@@ -190,8 +197,6 @@ + &wkup_pmx2 { + wkup_uart0_pins_default: wkup-uart0-default-pins { + pinctrl-single,pins = < +- J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (E25) WKUP_GPIO0_6.WKUP_UART0_CTSn */ +- J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (F28) WKUP_GPIO0_7.WKUP_UART0_RTSn */ + J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (D28) WKUP_UART0_RXD */ + J721S2_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (D27) WKUP_UART0_TXD */ + >; +@@ -356,6 +361,24 @@ + }; + }; + ++&main_i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c5_pins_default>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ exp5: gpio@20 { ++ compatible = "ti,tca6408"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ gpio-line-names = "CSI2_EXP_RSTZ", "CSI2_EXP_A_GPIO0", ++ "CSI2_EXP_A_GPIO1", "CSI2_EXP_A_GPIO2", ++ "CSI2_EXP_B_GPIO1", "CSI2_EXP_B_GPIO2", ++ "CSI2_EXP_B_GPIO3", "CSI2_EXP_B_GPIO4"; ++ }; ++}; ++ + &main_sdhci0 { + /* eMMC */ + status = "okay"; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-evm-pcie1-ep.dtso b/arch/arm64/boot/dts/ti/k3-j721s2-evm-pcie1-ep.dtso +--- a/arch/arm64/boot/dts/ti/k3-j721s2-evm-pcie1-ep.dtso 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-evm-pcie1-ep.dtso 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,53 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * DT Overlay for enabling PCIE1 instance in Endpoint Configuration with the ++ * J7 common processor board. ++ * ++ * J7 Common Processor Board Product Link: https://www.ti.com/tool/J721EXCPXEVM ++ * ++ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++/dts-v1/; ++/plugin/; ++ ++#include ++#include ++ ++#include "k3-pinctrl.h" ++ ++/* ++ * Since Root Complex and Endpoint modes are mutually exclusive ++ * disable Root Complex mode. ++ */ ++&pcie1_rc { ++ status = "disabled"; ++}; ++ ++&cbass_main { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ interrupt-parent = <&gic500>; ++ ++ pcie1_ep: pcie-ep@2910000 { ++ compatible = "ti,j7200-pcie-ep", "ti,j721e-pcie-ep"; ++ reg = <0x00 0x02910000 0x00 0x1000>, ++ <0x00 0x02917000 0x00 0x400>, ++ <0x00 0x0d800000 0x00 0x00800000>, ++ <0x00 0x18000000 0x00 0x08000000>; ++ reg-names = "intd_cfg", "user_cfg", "reg", "mem"; ++ interrupt-names = "link_state"; ++ interrupts = ; ++ ti,syscon-pcie-ctrl = <&scm_conf 0x074>; ++ max-link-speed = <3>; ++ num-lanes = <1>; ++ power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 276 41>; ++ clock-names = "fck"; ++ max-functions = /bits/ 8 <6>; ++ max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>; ++ dma-coherent; ++ phys = <&serdes0_pcie_link>; ++ phy-names = "pcie-phy"; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -45,7 +45,7 @@ + ranges = <0x00 0x00 0x00104000 0x18000>; + + usb_serdes_mux: mux-controller@0 { +- compatible = "mmio-mux"; ++ compatible = "reg-mux"; + reg = <0x0 0x4>; + #mux-control-cells = <1>; + mux-reg-masks = <0x0 0x8000000>; /* USB0 to SERDES0 lane 1/3 mux */ +@@ -58,11 +58,11 @@ + }; + + serdes_ln_ctrl: mux-controller@80 { +- compatible = "mmio-mux"; ++ compatible = "reg-mux"; + reg = <0x80 0x10>; + #mux-control-cells = <1>; +- mux-reg-masks = <0x80 0x3>, <0x84 0x3>, /* SERDES0 lane0/1 select */ +- <0x88 0x3>, <0x8c 0x3>; /* SERDES0 lane2/3 select */ ++ mux-reg-masks = <0x0 0x3>, <0x4 0x3>, /* SERDES0 lane0/1 select */ ++ <0x8 0x3>, <0xc 0x3>; /* SERDES0 lane2/3 select */ + }; + + ehrpwm_tbclk: clock-controller@140 { +@@ -766,6 +766,7 @@ + ti,itap-del-sel-sd-hs = <0x0>; + ti,itap-del-sel-sdr12 = <0x0>; + ti,itap-del-sel-sdr25 = <0x0>; ++ ti,itap-del-sel-ddr50 = <0x2>; + ti,clkbuf-sel = <0x7>; + ti,trm-icp = <0x8>; + dma-coherent; +@@ -775,7 +776,7 @@ + }; + + main_navss: bus@30000000 { +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>; +@@ -807,6 +808,7 @@ + ti,sci = <&sms>; + ti,sci-dev-id = <265>; + ti,interrupt-ranges = <0 0 256>; ++ ti,unmapped-event-sources = <&main_bcdma_csi>; + }; + + secure_proxy_main: mailbox@32c00000 { +@@ -1085,8 +1087,12 @@ + compatible = "ti,j721e-navss-main-udmap"; + reg = <0x0 0x31150000 0x0 0x100>, + <0x0 0x34000000 0x0 0x80000>, +- <0x0 0x35000000 0x0 0x200000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x0 0x35000000 0x0 0x200000>, ++ <0x0 0x30b00000 0x0 0x20000>, ++ <0x0 0x30c00000 0x0 0x8000>, ++ <0x0 0x30d00000 0x0 0x4000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&main_udmass_inta>; + #dma-cells = <1>; + +@@ -1103,6 +1109,21 @@ + ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */ + }; + ++ main_bcdma_csi: dma-controller@311a0000 { ++ compatible = "ti,j721s2-dmss-bcdma-csi"; ++ reg = <0x00 0x311a0000 0x00 0x100>, ++ <0x00 0x35d00000 0x00 0x20000>, ++ <0x00 0x35c00000 0x00 0x10000>, ++ <0x00 0x35e00000 0x00 0x80000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt"; ++ msi-parent = <&main_udmass_inta>; ++ #dma-cells = <3>; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <225>; ++ ti,sci-rm-range-rchan = <0x21>; ++ ti,sci-rm-range-tchan = <0x22>; ++ }; ++ + cpts@310d0000 { + compatible = "ti,j721e-cpts"; + reg = <0x0 0x310d0000 0x0 0x400>; +@@ -1211,6 +1232,128 @@ + }; + }; + ++ ti_csi2rx0: ticsi2rx@4500000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ reg = <0x00 0x04500000 0x00 0x1000>; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dmas = <&main_bcdma_csi 0 0x4940 0>; ++ dma-names = "rx0"; ++ power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ cdns_csi2rx0: csi-bridge@4504000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x00 0x04504000 0x00 0x1000>; ++ clocks = <&k3_clks 38 3>, <&k3_clks 38 1>, <&k3_clks 38 3>, ++ <&k3_clks 38 3>, <&k3_clks 38 4>, <&k3_clks 38 4>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy0>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi0_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi0_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi0_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi0_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ ti_csi2rx1: ticsi2rx@4510000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ reg = <0x00 0x04510000 0x00 0x1000>; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dmas = <&main_bcdma_csi 0 0x4960 0>; ++ dma-names = "rx0"; ++ power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ cdns_csi2rx1: csi-bridge@4514000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x00 0x04514000 0x00 0x1000>; ++ clocks = <&k3_clks 39 3>, <&k3_clks 39 1>, <&k3_clks 39 3>, ++ <&k3_clks 39 3>, <&k3_clks 39 4>, <&k3_clks 39 4>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy1>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi1_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi1_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi1_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi1_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi1_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ dphy0: phy@4580000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x00 0x04580000 0x00 0x1100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ dphy1: phy@4590000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x00 0x04590000 0x00 0x1100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ + serdes_wiz0: wiz@5060000 { + compatible = "ti,j721s2-wiz-10g"; + #address-cells = <1>; +@@ -1695,4 +1838,217 @@ + dss_ports: ports { + }; + }; ++ ++ main_r5fss0: r5fss@5c00000 { ++ compatible = "ti,j721s2-r5fss"; ++ ti,cluster-mode = <1>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x5c00000 0x00 0x5c00000 0x20000>, ++ <0x5d00000 0x00 0x5d00000 0x20000>; ++ power-domains = <&k3_pds 277 TI_SCI_PD_EXCLUSIVE>; ++ ++ main_r5fss0_core0: r5f@5c00000 { ++ compatible = "ti,j721s2-r5f"; ++ reg = <0x5c00000 0x00010000>, ++ <0x5c10000 0x00010000>; ++ reg-names = "atcm", "btcm"; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <279>; ++ ti,sci-proc-ids = <0x06 0xff>; ++ resets = <&k3_reset 279 1>; ++ firmware-name = "j721s2-main-r5f0_0-fw"; ++ ti,atcm-enable = <1>; ++ ti,btcm-enable = <1>; ++ ti,loczrama = <1>; ++ }; ++ ++ main_r5fss0_core1: r5f@5d00000 { ++ compatible = "ti,j721s2-r5f"; ++ reg = <0x5d00000 0x00010000>, ++ <0x5d10000 0x00010000>; ++ reg-names = "atcm", "btcm"; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <280>; ++ ti,sci-proc-ids = <0x07 0xff>; ++ resets = <&k3_reset 280 1>; ++ firmware-name = "j721s2-main-r5f0_1-fw"; ++ ti,atcm-enable = <1>; ++ ti,btcm-enable = <1>; ++ ti,loczrama = <1>; ++ }; ++ }; ++ ++ main_r5fss1: r5fss@5e00000 { ++ compatible = "ti,j721s2-r5fss"; ++ ti,cluster-mode = <1>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x5e00000 0x00 0x5e00000 0x20000>, ++ <0x5f00000 0x00 0x5f00000 0x20000>; ++ power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>; ++ ++ main_r5fss1_core0: r5f@5e00000 { ++ compatible = "ti,j721s2-r5f"; ++ reg = <0x5e00000 0x00010000>, ++ <0x5e10000 0x00010000>; ++ reg-names = "atcm", "btcm"; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <281>; ++ ti,sci-proc-ids = <0x08 0xff>; ++ resets = <&k3_reset 281 1>; ++ firmware-name = "j721s2-main-r5f1_0-fw"; ++ ti,atcm-enable = <1>; ++ ti,btcm-enable = <1>; ++ ti,loczrama = <1>; ++ }; ++ ++ main_r5fss1_core1: r5f@5f00000 { ++ compatible = "ti,j721s2-r5f"; ++ reg = <0x5f00000 0x00010000>, ++ <0x5f10000 0x00010000>; ++ reg-names = "atcm", "btcm"; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <282>; ++ ti,sci-proc-ids = <0x09 0xff>; ++ resets = <&k3_reset 282 1>; ++ firmware-name = "j721s2-main-r5f1_1-fw"; ++ ti,atcm-enable = <1>; ++ ti,btcm-enable = <1>; ++ ti,loczrama = <1>; ++ }; ++ }; ++ ++ c71_0: dsp@64800000 { ++ compatible = "ti,j721s2-c71-dsp"; ++ reg = <0x00 0x64800000 0x00 0x00080000>, ++ <0x00 0x64e00000 0x00 0x0000c000>; ++ reg-names = "l2sram", "l1dram"; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <8>; ++ ti,sci-proc-ids = <0x30 0xff>; ++ resets = <&k3_reset 8 1>; ++ firmware-name = "j721s2-c71_0-fw"; ++ status = "disabled"; ++ }; ++ ++ c71_1: dsp@65800000 { ++ compatible = "ti,j721s2-c71-dsp"; ++ reg = <0x00 0x65800000 0x00 0x00080000>, ++ <0x00 0x65e00000 0x00 0x0000c000>; ++ reg-names = "l2sram", "l1dram"; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <11>; ++ ti,sci-proc-ids = <0x31 0xff>; ++ resets = <&k3_reset 11 1>; ++ firmware-name = "j721s2-c71_1-fw"; ++ status = "disabled"; ++ }; ++ ++ main_esm: esm@700000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x700000 0x00 0x1000>; ++ ti,esm-pins = <688>, <689>; ++ bootph-pre-ram; ++ }; ++ ++ watchdog0: watchdog@2200000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2200000 0x00 0x100>; ++ clocks = <&k3_clks 286 1>; ++ power-domains = <&k3_pds 286 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 286 1>; ++ assigned-clock-parents = <&k3_clks 286 5>; ++ }; ++ ++ watchdog1: watchdog@2210000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2210000 0x00 0x100>; ++ clocks = <&k3_clks 287 1>; ++ power-domains = <&k3_pds 287 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 287 1>; ++ assigned-clock-parents = <&k3_clks 287 5>; ++ }; ++ ++ /* ++ * The following RTI instances are coupled with MCU R5Fs, c7x and ++ * GPU so keeping them reserved as these will be used by their ++ * respective firmware ++ */ ++ watchdog2: watchdog@22f0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x22f0000 0x00 0x100>; ++ clocks = <&k3_clks 290 1>; ++ power-domains = <&k3_pds 290 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 290 1>; ++ assigned-clock-parents = <&k3_clks 290 5>; ++ /* reserved for GPU */ ++ status = "reserved"; ++ }; ++ ++ watchdog3: watchdog@2300000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2300000 0x00 0x100>; ++ clocks = <&k3_clks 288 1>; ++ power-domains = <&k3_pds 288 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 288 1>; ++ assigned-clock-parents = <&k3_clks 288 5>; ++ /* reserved for C7X_0 */ ++ status = "reserved"; ++ }; ++ ++ watchdog4: watchdog@2310000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2310000 0x00 0x100>; ++ clocks = <&k3_clks 289 1>; ++ power-domains = <&k3_pds 289 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 289 1>; ++ assigned-clock-parents = <&k3_clks 289 5>; ++ /* reserved for C7X_1 */ ++ status = "reserved"; ++ }; ++ ++ watchdog5: watchdog@23c0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x23c0000 0x00 0x100>; ++ clocks = <&k3_clks 291 1>; ++ power-domains = <&k3_pds 291 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 291 1>; ++ assigned-clock-parents = <&k3_clks 291 5>; ++ /* reserved for MAIN_R5F0_0 */ ++ status = "reserved"; ++ }; ++ ++ watchdog6: watchdog@23d0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x23d0000 0x00 0x100>; ++ clocks = <&k3_clks 292 1>; ++ power-domains = <&k3_pds 292 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 292 1>; ++ assigned-clock-parents = <&k3_clks 292 5>; ++ /* reserved for MAIN_R5F0_1 */ ++ status = "reserved"; ++ }; ++ ++ watchdog7: watchdog@23e0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x23e0000 0x00 0x100>; ++ clocks = <&k3_clks 293 1>; ++ power-domains = <&k3_pds 293 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 293 1>; ++ assigned-clock-parents = <&k3_clks 293 5>; ++ /* reserved for MAIN_R5F1_0 */ ++ status = "reserved"; ++ }; ++ ++ watchdog8: watchdog@23f0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x23f0000 0x00 0x100>; ++ clocks = <&k3_clks 294 1>; ++ power-domains = <&k3_pds 294 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 294 1>; ++ assigned-clock-parents = <&k3_clks 294 5>; ++ /* reserved for MAIN_R5F1_1 */ ++ status = "reserved"; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -34,9 +34,16 @@ + }; + }; + +- chipid@43000014 { +- compatible = "ti,am654-chipid"; +- reg = <0x00 0x43000014 0x00 0x4>; ++ wkup_conf: bus@43000000 { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x00 0x43000000 0x20000>; ++ ++ chipid: chipid@14 { ++ compatible = "ti,am654-chipid"; ++ reg = <0x14 0x4>; ++ }; + }; + + secure_proxy_sa3: mailbox@43600000 { +@@ -443,7 +450,7 @@ + }; + + mcu_navss: bus@28380000 { +- compatible = "simple-mfd"; ++ compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>; +@@ -471,8 +478,12 @@ + compatible = "ti,j721e-navss-mcu-udmap"; + reg = <0x0 0x285c0000 0x0 0x100>, + <0x0 0x2a800000 0x0 0x40000>, +- <0x0 0x2aa00000 0x0 0x40000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x0 0x2aa00000 0x0 0x40000>, ++ <0x0 0x284a0000 0x0 0x4000>, ++ <0x0 0x284c0000 0x0 0x4000>, ++ <0x0 0x28400000 0x0 0x2000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&main_udmass_inta>; + #dma-cells = <1>; + +@@ -655,4 +666,84 @@ + power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>; + #thermal-sensor-cells = <1>; + }; ++ ++ mcu_r5fss0: r5fss@41000000 { ++ compatible = "ti,j721s2-r5fss"; ++ ti,cluster-mode = <1>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x41000000 0x00 0x41000000 0x20000>, ++ <0x41400000 0x00 0x41400000 0x20000>; ++ power-domains = <&k3_pds 283 TI_SCI_PD_EXCLUSIVE>; ++ ++ mcu_r5fss0_core0: r5f@41000000 { ++ compatible = "ti,j721s2-r5f"; ++ reg = <0x41000000 0x00010000>, ++ <0x41010000 0x00010000>; ++ reg-names = "atcm", "btcm"; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <284>; ++ ti,sci-proc-ids = <0x01 0xff>; ++ resets = <&k3_reset 284 1>; ++ firmware-name = "j721s2-mcu-r5f0_0-fw"; ++ ti,atcm-enable = <1>; ++ ti,btcm-enable = <1>; ++ ti,loczrama = <1>; ++ }; ++ ++ mcu_r5fss0_core1: r5f@41400000 { ++ compatible = "ti,j721s2-r5f"; ++ reg = <0x41400000 0x00010000>, ++ <0x41410000 0x00010000>; ++ reg-names = "atcm", "btcm"; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <285>; ++ ti,sci-proc-ids = <0x02 0xff>; ++ resets = <&k3_reset 285 1>; ++ firmware-name = "j721s2-mcu-r5f0_1-fw"; ++ ti,atcm-enable = <1>; ++ ti,btcm-enable = <1>; ++ ti,loczrama = <1>; ++ }; ++ }; ++ ++ mcu_esm: esm@40800000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x40800000 0x00 0x1000>; ++ ti,esm-pins = <95>; ++ bootph-pre-ram; ++ }; ++ ++ wkup_esm: esm@42080000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x42080000 0x00 0x1000>; ++ ti,esm-pins = <63>; ++ bootph-pre-ram; ++ }; ++ ++ /* ++ * The 2 RTI instances are couple with MCU R5Fs so keeping them ++ * reserved as these will be used by their respective firmware ++ */ ++ mcu_watchdog0: watchdog@40600000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x40600000 0x00 0x100>; ++ clocks = <&k3_clks 295 1>; ++ power-domains = <&k3_pds 295 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 295 1>; ++ assigned-clock-parents = <&k3_clks 295 5>; ++ /* reserved for MCU_R5F0_0 */ ++ status = "reserved"; ++ }; ++ ++ mcu_watchdog1: watchdog@40610000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x40610000 0x00 0x100>; ++ clocks = <&k3_clks 296 1>; ++ power-domains = <&k3_pds 296 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 296 1>; ++ assigned-clock-parents = <&k3_clks 296 5>; ++ /* reserved for MCU_R5F0_1 */ ++ status = "reserved"; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -29,6 +29,108 @@ + alignment = <0x1000>; + no-map; + }; ++ ++ mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa1000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa1100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa2000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core0_memory_region: r5f-memory@a2100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa2100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa3000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss0_core1_memory_region: r5f-memory@a3100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa3100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa4000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core0_memory_region: r5f-memory@a4100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa4100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa5000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ main_r5fss1_core1_memory_region: r5f-memory@a5100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa5100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ c71_0_dma_memory_region: c71-dma-memory@a6000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa6000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ c71_0_memory_region: c71-memory@a6100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa6100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ c71_1_dma_memory_region: c71-dma-memory@a7000000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa7000000 0x00 0x100000>; ++ no-map; ++ }; ++ ++ c71_1_memory_region: c71-memory@a7100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa7100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ rtos_ipc_memory_region: ipc-memories@a8000000 { ++ reg = <0x00 0xa8000000 0x00 0x01c00000>; ++ alignment = <0x1000>; ++ no-map; ++ }; + }; + + mux0: mux-controller { +@@ -70,6 +172,15 @@ + }; + }; + ++&wkup_pmx1 { ++ pmic_irq_pins_default: pmic-irq-default-pins { ++ pinctrl-single,pins = < ++ /* (C21) MCU_OSPI1_CSn1.WKUP_GPIO0_39 */ ++ J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 7) ++ >; ++ }; ++}; ++ + &wkup_pmx2 { + wkup_i2c0_pins_default: wkup-i2c0-default-pins { + pinctrl-single,pins = < +@@ -106,6 +217,190 @@ + compatible = "atmel,24c256"; + reg = <0x50>; + }; ++ ++ tps659411: pmic@48 { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x48>; ++ system-power-controller; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_irq_pins_default>; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <39 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ti,primary-pmic; ++ buck1234-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ bucka1234: buck1234 { ++ regulator-name = "vdd_cpu_avs"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <900000>; ++ regulator-boot-on; ++ regulator-always-on; ++ bootph-pre-ram; ++ }; ++ ++ bucka5: buck5 { ++ regulator-name = "vdd_mcu_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa1: ldo1 { ++ regulator-name = "vdd_mcuwk_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa2: ldo2 { ++ regulator-name = "vdd_mcu_gpioret_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa3: ldo3 { ++ regulator-name = "vdd_mcuio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa4: ldo4 { ++ regulator-name = "vda_mcu_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ tps659414: pmic@4c { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x4c>; ++ system-power-controller; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <39 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ buck1-supply = <&vsys_3v3>; ++ buck2-supply = <&vsys_3v3>; ++ buck3-supply = <&vsys_3v3>; ++ buck4-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ buckb1: buck1 { ++ regulator-name = "vdd_io_1v8_reg"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ buckb2: buck2 { ++ regulator-name = "vdd_fpd_1v1"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buckb3: buck3 { ++ regulator-name = "vdd_phy_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buckb4: buck4 { ++ regulator-name = "vdd_ddr_1v1"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buckb5: buck5 { ++ regulator-name = "vdd_ram_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob1: ldo1 { ++ regulator-name = "vdd_wk_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob2: ldo2 { ++ regulator-name = "vdd_gpioret_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob3: ldo3 { ++ regulator-name = "vda_dll_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldob4: ldo4 { ++ regulator-name = "vda_pll_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ lp876411: pmic@58 { ++ compatible = "ti,lp8764-q1"; ++ reg = <0x58>; ++ system-power-controller; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <39 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ buck1234-supply = <&vsys_3v3>; ++ ++ regulators { ++ buckc1234: buck1234 { ++ regulator-name = "vdd_core_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; + }; + + &main_i2c0 { +@@ -151,3 +446,109 @@ + cdns,read-delay = <4>; + }; + }; ++ ++&mailbox0_cluster0 { ++ status = "okay"; ++ interrupts = <436>; ++ mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster1 { ++ status = "okay"; ++ interrupts = <432>; ++ mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster2 { ++ status = "okay"; ++ interrupts = <428>; ++ mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mailbox0_cluster4 { ++ status = "okay"; ++ interrupts = <420>; ++ mbox_c71_0: mbox-c71-0 { ++ ti,mbox-rx = <0 0 0>; ++ ti,mbox-tx = <1 0 0>; ++ }; ++ ++ mbox_c71_1: mbox-c71-1 { ++ ti,mbox-rx = <2 0 0>; ++ ti,mbox-tx = <3 0 0>; ++ }; ++}; ++ ++&mcu_r5fss0_core0 { ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>; ++ memory-region = <&mcu_r5fss0_core0_dma_memory_region>, ++ <&mcu_r5fss0_core0_memory_region>; ++}; ++ ++&mcu_r5fss0_core1 { ++ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>; ++ memory-region = <&mcu_r5fss0_core1_dma_memory_region>, ++ <&mcu_r5fss0_core1_memory_region>; ++}; ++ ++&main_r5fss0_core0 { ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>; ++ memory-region = <&main_r5fss0_core0_dma_memory_region>, ++ <&main_r5fss0_core0_memory_region>; ++}; ++ ++&main_r5fss0_core1 { ++ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>; ++ memory-region = <&main_r5fss0_core1_dma_memory_region>, ++ <&main_r5fss0_core1_memory_region>; ++}; ++ ++&main_r5fss1_core0 { ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>; ++ memory-region = <&main_r5fss1_core0_dma_memory_region>, ++ <&main_r5fss1_core0_memory_region>; ++}; ++ ++&main_r5fss1_core1 { ++ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>; ++ memory-region = <&main_r5fss1_core1_dma_memory_region>, ++ <&main_r5fss1_core1_memory_region>; ++}; ++ ++&c71_0 { ++ status = "okay"; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_0>; ++ memory-region = <&c71_0_dma_memory_region>, ++ <&c71_0_memory_region>; ++}; ++ ++&c71_1 { ++ status = "okay"; ++ mboxes = <&mailbox0_cluster4 &mbox_c71_1>; ++ memory-region = <&c71_1_dma_memory_region>, ++ <&c71_1_memory_region>; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j722s.dtsi b/arch/arm64/boot/dts/ti/k3-j722s.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j722s.dtsi 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j722s.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,89 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/* ++ * Device Tree Source for J722S SoC Family ++ * ++ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/ ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "k3-am62p5.dtsi" ++ ++/ { ++ model = "Texas Instruments K3 J722S SoC"; ++ compatible = "ti,j722s"; ++ ++ cbass_main: bus@f0000 { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ ranges = <0x00 0x000f0000 0x00 0x000f0000 0x00 0x00030000>, /* Main MMRs */ ++ <0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */ ++ <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */ ++ <0x00 0x00703000 0x00 0x00703000 0x00 0x00000200>, /* USB0 debug trace */ ++ <0x00 0x0070c000 0x00 0x0070c000 0x00 0x00000200>, /* USB1 debug trace */ ++ <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Timesync router */ ++ <0x00 0x01000000 0x00 0x01000000 0x00 0x01b28400>, /* First peripheral window */ ++ <0x00 0x08000000 0x00 0x08000000 0x00 0x00200000>, /* Main CPSW */ ++ <0x00 0x0d000000 0x00 0x0d000000 0x00 0x00800000>, /* PCIE_0 */ ++ <0x00 0x0e000000 0x00 0x0e000000 0x00 0x01d20000>, /* Second peripheral window */ ++ <0x00 0x0fd80000 0x00 0x0fd80000 0x00 0x00080000>, /* GPU */ ++ <0x00 0x0fd20000 0x00 0x0fd20000 0x00 0x00000100>, /* JPEGENC0_CORE */ ++ <0x00 0x0fd20200 0x00 0x0fd20200 0x00 0x00000200>, /* JPEGENC0_CORE_MMU */ ++ <0x00 0x20000000 0x00 0x20000000 0x00 0x0a008000>, /* Third peripheral window */ ++ <0x00 0x30040000 0x00 0x30040000 0x00 0x00080000>, /* PRUSS-M */ ++ <0x00 0x301C0000 0x00 0x301C0000 0x00 0x00001000>, /* DPHY-TX */ ++ <0x00 0x30101000 0x00 0x30101000 0x00 0x00080100>, /* CSI window */ ++ <0x00 0x30200000 0x00 0x30200000 0x00 0x00010000>, /* DSS */ ++ <0x00 0x30210000 0x00 0x30210000 0x00 0x00010000>, /* VPU */ ++ <0x00 0x30220000 0x00 0x30220000 0x00 0x00010000>, /* DSS1 */ ++ <0x00 0x30270000 0x00 0x30270000 0x00 0x00010000>, /* DSI-base1 */ ++ <0x00 0x30500000 0x00 0x30500000 0x00 0x00100000>, /* DSI-base2 */ ++ <0x00 0x31000000 0x00 0x31000000 0x00 0x00050000>, /* USB0 DWC3 Core window */ ++ <0x00 0x31200000 0x00 0x31200000 0x00 0x00040000>, /* USB1 DWC3 Core window */ ++ <0x00 0x40900000 0x00 0x40900000 0x00 0x00030000>, /* SA3UL */ ++ <0x00 0x43600000 0x00 0x43600000 0x00 0x00010000>, /* SA3 sproxy data */ ++ <0x00 0x44043000 0x00 0x44043000 0x00 0x00000fe0>, /* TI SCI DEBUG */ ++ <0x00 0x44860000 0x00 0x44860000 0x00 0x00040000>, /* SA3 sproxy config */ ++ <0x00 0x48000000 0x00 0x48000000 0x00 0x06408000>, /* DMSS */ ++ <0x00 0x60000000 0x00 0x60000000 0x00 0x08000000>, /* FSS0 DAT1 */ ++ <0x00 0x68000000 0x00 0x68000000 0x00 0x08000000>, /* PCIe0 DAT0 */ ++ <0x00 0x70000000 0x00 0x70000000 0x00 0x00040000>, /* OCSRAM */ ++ <0x00 0x78400000 0x00 0x78400000 0x00 0x00008000>, /* MAIN R5FSS0 ATCM */ ++ <0x00 0x78500000 0x00 0x78500000 0x00 0x00008000>, /* MAIN R5FSS0 BTCM */ ++ <0x00 0x7e000000 0x00 0x7e000000 0x00 0x00200000>, /* C7X_0 L2SRAM */ ++ <0x00 0x7e200000 0x00 0x7e200000 0x00 0x00200000>, /* C7X_1 L2SRAM */ ++ <0x01 0x00000000 0x01 0x00000000 0x00 0x00310000>, /* A53 PERIPHBASE */ ++ <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS0 DAT3 */ ++ <0x06 0x00000000 0x06 0x00000000 0x01 0x00000000>, /* PCIe0 DAT1 */ ++ ++ /* MCU Domain Range */ ++ <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>, ++ <0x00 0x79000000 0x00 0x79000000 0x00 0x00008000>, ++ <0x00 0x79020000 0x00 0x79020000 0x00 0x00008000>, ++ <0x00 0x79100000 0x00 0x79100000 0x00 0x00040000>, ++ <0x00 0x79140000 0x00 0x79140000 0x00 0x00040000>, ++ ++ /* Wakeup Domain Range */ ++ <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, ++ <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>, ++ <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>, ++ <0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>, ++ <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; ++ }; ++}; ++ ++/* Main domain overrides */ ++ ++&inta_main_dmss { ++ ti,interrupt-ranges = <7 71 21>; ++}; ++ ++&oc_sram { ++ reg = <0x00 0x70000000 0x00 0x40000>; ++ ranges = <0x00 0x00 0x70000000 0x40000>; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts +--- a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts 1969-12-31 19:00:00.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,383 @@ ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/* ++ * Device Tree file for the J722S EVM ++ * Copyright (C) 2024 Texas Instruments Incorporated - https://www.ti.com/ ++ * ++ * Schematics: https://www.ti.com/lit/zip/sprr495 ++ */ ++ ++/dts-v1/; ++ ++#include ++#include "k3-j722s.dtsi" ++ ++/ { ++ compatible = "ti,j722s-evm", "ti,j722s"; ++ model = "Texas Instruments J722S EVM"; ++ ++ aliases { ++ serial0 = &wkup_uart0; ++ serial2 = &main_uart0; ++ mmc0 = &sdhci0; ++ mmc1 = &sdhci1; ++ }; ++ ++ chosen { ++ stdout-path = &main_uart0; ++ }; ++ ++ memory@80000000 { ++ /* 8G RAM */ ++ reg = <0x00000000 0x80000000 0x00000000 0x80000000>, ++ <0x00000008 0x80000000 0x00000001 0x80000000>; ++ device_type = "memory"; ++ bootph-pre-ram; ++ }; ++ ++ reserved_memory: reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ secure_tfa_ddr: tfa@9e780000 { ++ reg = <0x00 0x9e780000 0x00 0x80000>; ++ no-map; ++ }; ++ ++ secure_ddr: optee@9e800000 { ++ reg = <0x00 0x9e800000 0x00 0x01800000>; ++ no-map; ++ }; ++ ++ wkup_r5fss0_core0_memory_region: r5f-memory@a0100000 { ++ compatible = "shared-dma-pool"; ++ reg = <0x00 0xa0100000 0x00 0xf00000>; ++ no-map; ++ }; ++ ++ }; ++ ++ vmain_pd: regulator-0 { ++ /* TPS65988 PD CONTROLLER OUTPUT */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vmain_pd"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ regulator-boot-on; ++ bootph-all; ++ }; ++ ++ vsys_5v0: regulator-vsys5v0 { ++ /* Output of LM5140 */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vsys_5v0"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vmain_pd>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vdd_mmc1: regulator-mmc1 { ++ /* TPS22918DBVR */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd_mmc1"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ enable-active-high; ++ gpio = <&exp1 15 GPIO_ACTIVE_HIGH>; ++ bootph-all; ++ }; ++ ++ vdd_sd_dv: regulator-TLV71033 { ++ compatible = "regulator-gpio"; ++ regulator-name = "tlv71033"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vdd_sd_dv_pins_default>; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ vin-supply = <&vsys_5v0>; ++ gpios = <&main_gpio0 70 GPIO_ACTIVE_HIGH>; ++ states = <1800000 0x0>, ++ <3300000 0x1>; ++ }; ++ ++ vsys_io_1v8: regulator-vsys-io-1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vsys_io_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vsys_io_1v2: regulator-vsys-io-1v2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vsys_io_1v2"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++}; ++ ++&main_pmx0 { ++ ++ main_i2c0_pins_default: main-i2c0-default-pins { ++ pinctrl-single,pins = < ++ J722S_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (D23) I2C0_SCL */ ++ J722S_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (B22) I2C0_SDA */ ++ >; ++ bootph-all; ++ }; ++ ++ main_uart0_pins_default: main-uart0-default-pins { ++ pinctrl-single,pins = < ++ J722S_IOPAD(0x01c8, PIN_INPUT, 0) /* (A22) UART0_RXD */ ++ J722S_IOPAD(0x01cc, PIN_OUTPUT, 0) /* (B22) UART0_TXD */ ++ >; ++ bootph-all; ++ }; ++ ++ vdd_sd_dv_pins_default: vdd-sd-dv-default-pins { ++ pinctrl-single,pins = < ++ J722S_IOPAD(0x0120, PIN_INPUT, 7) /* (F27) MMC2_CMD.GPIO0_70 */ ++ >; ++ bootph-all; ++ }; ++ ++ main_mmc1_pins_default: main-mmc1-default-pins { ++ pinctrl-single,pins = < ++ J722S_IOPAD(0x023c, PIN_INPUT, 0) /* (H22) MMC1_CMD */ ++ J722S_IOPAD(0x0234, PIN_OUTPUT, 0) /* (H24) MMC1_CLK */ ++ J722S_IOPAD(0x0230, PIN_INPUT, 0) /* (H23) MMC1_DAT0 */ ++ J722S_IOPAD(0x022c, PIN_INPUT_PULLUP, 0) /* (H20) MMC1_DAT1 */ ++ J722S_IOPAD(0x0228, PIN_INPUT_PULLUP, 0) /* (J23) MMC1_DAT2 */ ++ J722S_IOPAD(0x0224, PIN_INPUT_PULLUP, 0) /* (H25) MMC1_DAT3 */ ++ J722S_IOPAD(0x0240, PIN_INPUT, 0) /* (B24) MMC1_SDCD */ ++ >; ++ bootph-all; ++ }; ++ ++ mdio_pins_default: mdio-default-pins { ++ pinctrl-single,pins = < ++ J722S_IOPAD(0x0160, PIN_OUTPUT, 0) /* (AC24) MDIO0_MDC */ ++ J722S_IOPAD(0x015c, PIN_INPUT, 0) /* (AD25) MDIO0_MDIO */ ++ >; ++ }; ++ ++ ospi0_pins_default: ospi0-default-pins { ++ pinctrl-single,pins = < ++ J722S_IOPAD(0x0000, PIN_OUTPUT, 0) /* (L24) OSPI0_CLK */ ++ J722S_IOPAD(0x002c, PIN_OUTPUT, 0) /* (K26) OSPI0_CSn0 */ ++ J722S_IOPAD(0x000c, PIN_INPUT, 0) /* (K27) OSPI0_D0 */ ++ J722S_IOPAD(0x0010, PIN_INPUT, 0) /* (L27) OSPI0_D1 */ ++ J722S_IOPAD(0x0014, PIN_INPUT, 0) /* (L26) OSPI0_D2 */ ++ J722S_IOPAD(0x0018, PIN_INPUT, 0) /* (L25) OSPI0_D3 */ ++ J722S_IOPAD(0x001c, PIN_INPUT, 0) /* (L21) OSPI0_D4 */ ++ J722S_IOPAD(0x0020, PIN_INPUT, 0) /* (M26) OSPI0_D5 */ ++ J722S_IOPAD(0x0024, PIN_INPUT, 0) /* (N27) OSPI0_D6 */ ++ J722S_IOPAD(0x0028, PIN_INPUT, 0) /* (M27) OSPI0_D7 */ ++ J722S_IOPAD(0x0008, PIN_INPUT, 0) /* (L22) OSPI0_DQS */ ++ >; ++ bootph-all; ++ }; ++ ++ rgmii1_pins_default: rgmii1-default-pins { ++ pinctrl-single,pins = < ++ J722S_IOPAD(0x014c, PIN_INPUT, 0) /* (AC25) RGMII1_RD0 */ ++ J722S_IOPAD(0x0150, PIN_INPUT, 0) /* (AD27) RGMII1_RD1 */ ++ J722S_IOPAD(0x0154, PIN_INPUT, 0) /* (AE24) RGMII1_RD2 */ ++ J722S_IOPAD(0x0158, PIN_INPUT, 0) /* (AE26) RGMII1_RD3 */ ++ J722S_IOPAD(0x0148, PIN_INPUT, 0) /* (AE27) RGMII1_RXC */ ++ J722S_IOPAD(0x0144, PIN_INPUT, 0) /* (AD23) RGMII1_RX_CTL */ ++ J722S_IOPAD(0x0134, PIN_OUTPUT, 0) /* (AF27) RGMII1_TD0 */ ++ J722S_IOPAD(0x0138, PIN_OUTPUT, 0) /* (AE23) RGMII1_TD1 */ ++ J722S_IOPAD(0x013c, PIN_OUTPUT, 0) /* (AG25) RGMII1_TD2 */ ++ J722S_IOPAD(0x0140, PIN_OUTPUT, 0) /* (AF24) RGMII1_TD3 */ ++ J722S_IOPAD(0x0130, PIN_OUTPUT, 0) /* (AG26) RGMII1_TXC */ ++ J722S_IOPAD(0x012c, PIN_OUTPUT, 0) /* (AF25) RGMII1_TX_CTL */ ++ >; ++ }; ++}; ++ ++&cpsw3g { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii1_pins_default>; ++}; ++ ++&cpsw3g_mdio { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mdio_pins_default>; ++ ++ cpsw3g_phy0: ethernet-phy@0 { ++ reg = <0>; ++ ti,rx-internal-delay = ; ++ ti,fifo-depth = ; ++ ti,min-output-impedance; ++ }; ++}; ++ ++&cpsw_port1 { ++ phy-mode = "rgmii-rxid"; ++ phy-handle = <&cpsw3g_phy0>; ++}; ++ ++&cpsw_port2 { ++ status = "disabled"; ++}; ++ ++&main_gpio1 { ++ status = "okay"; ++}; ++ ++&main_uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_uart0_pins_default>; ++ status = "okay"; ++ bootph-all; ++}; ++ ++&mcu_pmx0 { ++ ++ wkup_uart0_pins_default: wkup-uart0-default-pins { ++ pinctrl-single,pins = < ++ J722S_MCU_IOPAD(0x02c, PIN_INPUT, 0) /* (C7) WKUP_UART0_CTSn */ ++ J722S_MCU_IOPAD(0x030, PIN_OUTPUT, 0) /* (C6) WKUP_UART0_RTSn */ ++ J722S_MCU_IOPAD(0x024, PIN_INPUT, 0) /* (D8) WKUP_UART0_RXD */ ++ J722S_MCU_IOPAD(0x028, PIN_OUTPUT, 0) /* (D7) WKUP_UART0_TXD */ ++ >; ++ bootph-all; ++ }; ++ ++ wkup_i2c0_pins_default: wkup-i2c0-default-pins { ++ pinctrl-single,pins = < ++ J722S_MCU_IOPAD(0x04c, PIN_INPUT_PULLUP, 0) /* (C7) WKUP_I2C0_SCL */ ++ J722S_MCU_IOPAD(0x050, PIN_INPUT_PULLUP, 0) /* (C6) WKUP_I2C1_SDA */ ++ >; ++ bootph-all; ++ }; ++}; ++ ++&wkup_uart0 { ++ /* WKUP UART0 is used by Device Manager firmware */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wkup_uart0_pins_default>; ++ status = "reserved"; ++ bootph-all; ++}; ++ ++&wkup_i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&wkup_i2c0_pins_default>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ bootph-all; ++}; ++ ++&main_i2c0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c0_pins_default>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ bootph-all; ++ ++ exp1: gpio@23 { ++ compatible = "ti,tca6424"; ++ reg = <0x23>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ gpio-line-names = "TRC_MUX_SEL", "OSPI/ONAND_MUX_SEL", ++ "MCASP1_FET_SEL", "CTRL_PM_I2C_OE#", ++ "CSI_VIO_SEL", "USB2.0_MUX_SEL", ++ "CSI01_MUX_SEL_2", "CSI23_MUX_SEL_2", ++ "LMK1_OE1", "LMK1_OE0", ++ "LMK2_OE0", "LMK2_OE1", ++ "GPIO_RGMII1_RST#", "GPIO_AUD_RSTn", ++ "GPIO_eMMC_RSTn", "GPIO_uSD_PWR_EN", ++ "USER_LED2", "MCAN0_STB", ++ "PCIe0_1L_RC_RSTz", "PCIe0_1L_PRSNT#", ++ "ENET1_EXP_SPARE2", "ENET1_EXP_PWRDN", ++ "PD_I2ENET1_I2CMUX_SELC_IRQ", "ENET1_EXP_RESETZ"; ++ }; ++}; ++ ++&ospi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ospi0_pins_default>; ++ status = "okay"; ++ ++ flash@0 { ++ compatible = "jedec,spi-nor"; ++ reg = <0x0>; ++ spi-tx-bus-width = <8>; ++ spi-rx-bus-width = <8>; ++ spi-max-frequency = <25000000>; ++ cdns,tshsl-ns = <60>; ++ cdns,tsd2d-ns = <60>; ++ cdns,tchsh-ns = <60>; ++ cdns,tslch-ns = <60>; ++ cdns,read-delay = <4>; ++ bootph-all; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ label = "ospi.tiboot3"; ++ reg = <0x00 0x80000>; ++ }; ++ ++ partition@80000 { ++ label = "ospi.tispl"; ++ reg = <0x80000 0x200000>; ++ }; ++ ++ partition@280000 { ++ label = "ospi.u-boot"; ++ reg = <0x280000 0x400000>; ++ }; ++ ++ partition@680000 { ++ label = "ospi.env"; ++ reg = <0x680000 0x40000>; ++ }; ++ ++ partition@6c0000 { ++ label = "ospi.env.backup"; ++ reg = <0x6c0000 0x40000>; ++ }; ++ ++ partition@800000 { ++ label = "ospi.rootfs"; ++ reg = <0x800000 0x37c0000>; ++ }; ++ ++ partition@3fc0000 { ++ label = "ospi.phypattern"; ++ reg = <0x3fc0000 0x40000>; ++ }; ++ }; ++ }; ++ ++}; ++ ++&sdhci1 { ++ /* SD/MMC */ ++ vmmc-supply = <&vdd_mmc1>; ++ vqmmc-supply = <&vdd_sd_dv>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_mmc1_pins_default>; ++ ti,driver-strength-ohm = <50>; ++ disable-wp; ++ no-1-8-v; ++ status = "okay"; ++ bootph-all; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,10 +1,10 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for J784S4 SoC Family + * + * TRM (SPRUJ43 JULY 2022): https://www.ti.com/lit/zip/spruj52 + * +- * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +@@ -235,6 +235,8 @@ + ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */ + <0x00 0x00600000 0x00 0x00600000 0x00 0x00031100>, /* GPIO */ + <0x00 0x01000000 0x00 0x01000000 0x00 0x0d000000>, /* Most peripherals */ ++ <0x00 0x04210000 0x00 0x04210000 0x00 0x00010000>, /* VPU0 */ ++ <0x00 0x04220000 0x00 0x04220000 0x00 0x00010000>, /* VPU1 */ + <0x00 0x0d000000 0x00 0x0d000000 0x00 0x01000000>, /* PCIe Core*/ + <0x00 0x10000000 0x00 0x10000000 0x00 0x08000000>, /* PCIe0 DAT0 */ + <0x00 0x18000000 0x00 0x18000000 0x00 0x08000000>, /* PCIe1 DAT0 */ +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts +--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts 2024-03-28 11:26:09.897017444 -0400 +@@ -1,6 +1,6 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* +- * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + * EVM Board Schematics: https://www.ti.com/lit/zip/sprr458 + */ +@@ -31,6 +31,7 @@ + + memory@80000000 { + device_type = "memory"; ++ bootph-all; + /* 32G RAM */ + reg = <0x00 0x80000000 0x00 0x80000000>, + <0x08 0x80000000 0x07 0x80000000>; +@@ -249,6 +250,32 @@ + states = <1800000 0x0>, + <3300000 0x1>; + }; ++ ++ dp0_pwr_3v3: regulator-dp0-prw { ++ compatible = "regulator-fixed"; ++ regulator-name = "dp0-pwr"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&exp4 0 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ dp0: connector-dp0 { ++ compatible = "dp-connector"; ++ label = "DP0"; ++ type = "full-size"; ++ dp-pwr-supply = <&dp0_pwr_3v3>; ++ ++ port { ++ dp0_connector_in: endpoint { ++ remote-endpoint = <&dp0_out>; ++ }; ++ }; ++ }; ++}; ++ ++&wkup_gpio0 { ++ status = "okay"; + }; + + &main_pmx0 { +@@ -270,6 +297,13 @@ + >; + }; + ++ main_i2c5_pins_default: main-i2c5-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x01c, PIN_INPUT, 8) /* (AG34) MCAN15_TX.I2C5_SCL */ ++ J784S4_IOPAD(0x018, PIN_INPUT, 8) /* (AK36) MCAN14_RX.I2C5_SDA */ ++ >; ++ }; ++ + main_mmc1_pins_default: main-mmc1-default-pins { + bootph-all; + pinctrl-single,pins = < +@@ -289,6 +323,19 @@ + J784S4_IOPAD(0x020, PIN_INPUT, 7) /* (AJ35) MCAN15_RX.GPIO0_8 */ + >; + }; ++ ++ dp0_pins_default: dp0-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x0cc, PIN_INPUT, 12) /* (AM37) SPI0_CS0.DP0_HPD */ ++ >; ++ }; ++ ++ main_i2c4_pins_default: main-i2c4-default-pins { ++ pinctrl-single,pins = < ++ J784S4_IOPAD(0x014, PIN_INPUT_PULLUP, 8) /* (AG33) MCAN14_TX.I2C4_SCL */ ++ J784S4_IOPAD(0x010, PIN_INPUT_PULLUP, 8) /* (AH33) MCAN13_RX.I2C4_SDA */ ++ >; ++ }; + }; + + &wkup_pmx2 { +@@ -296,8 +343,6 @@ + wkup_uart0_pins_default: wkup-uart0-default-pins { + bootph-all; + pinctrl-single,pins = < +- J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (L37) WKUP_GPIO0_6.WKUP_UART0_CTSn */ +- J721S2_WKUP_IOPAD(0x074, PIN_INPUT, 0) /* (L36) WKUP_GPIO0_7.WKUP_UART0_RTSn */ + J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (K35) WKUP_UART0_RXD */ + J721S2_WKUP_IOPAD(0x04c, PIN_INPUT, 0) /* (K34) WKUP_UART0_TXD */ + >; +@@ -372,6 +417,17 @@ + }; + }; + ++&wkup_pmx1 { ++ status = "okay"; ++ ++ pmic_irq_pins_default: pmic-irq-default-pins { ++ pinctrl-single,pins = < ++ /* (G33) MCU_OSPI1_CSn1.WKUP_GPIO0_39 */ ++ J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 7) ++ >; ++ }; ++}; ++ + &wkup_pmx0 { + bootph-all; + mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-default-pins { +@@ -436,6 +492,93 @@ + compatible = "atmel,24c256"; + reg = <0x50>; + }; ++ ++ tps659413: pmic@48 { ++ compatible = "ti,tps6594-q1"; ++ reg = <0x48>; ++ system-power-controller; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_irq_pins_default>; ++ interrupt-parent = <&wkup_gpio0>; ++ interrupts = <39 IRQ_TYPE_EDGE_FALLING>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ ti,primary-pmic; ++ buck12-supply = <&vsys_3v3>; ++ buck3-supply = <&vsys_3v3>; ++ buck4-supply = <&vsys_3v3>; ++ buck5-supply = <&vsys_3v3>; ++ ldo1-supply = <&vsys_3v3>; ++ ldo2-supply = <&vsys_3v3>; ++ ldo3-supply = <&vsys_3v3>; ++ ldo4-supply = <&vsys_3v3>; ++ ++ regulators { ++ bucka12: buck12 { ++ regulator-name = "vdd_ddr_1v1"; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka3: buck3 { ++ regulator-name = "vdd_ram_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka4: buck4 { ++ regulator-name = "vdd_io_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ bucka5: buck5 { ++ regulator-name = "vdd_mcu_0v85"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa1: ldo1 { ++ regulator-name = "vdd_mcuio_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa2: ldo2 { ++ regulator-name = "vdd_mcuio_3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa3: ldo3 { ++ regulator-name = "vds_dll_0v8"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldoa4: ldo4 { ++ regulator-name = "vda_mcu_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; + }; + + &mcu_uart0 { +@@ -623,6 +766,24 @@ + }; + }; + ++&main_i2c5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c5_pins_default>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ exp5: gpio@20 { ++ compatible = "ti,tca6408"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ gpio-line-names = "CSI2_EXP_RSTZ", "CSI2_EXP_A_GPIO0", ++ "CSI2_EXP_A_GPIO1", "CSI2_EXP_A_GPIO3", ++ "CSI2_EXP_B_GPIO1", "CSI2_EXP_B_GPIO2", ++ "CSI2_EXP_B_GPIO3", "CSI2_EXP_B_GPIO4"; ++ }; ++}; ++ + &main_sdhci0 { + bootph-all; + /* eMMC */ +@@ -862,3 +1023,85 @@ + ti,adc-channels = <0 1 2 3 4 5 6 7>; + }; + }; ++ ++&serdes_refclk { ++ status = "okay"; ++ clock-frequency = <100000000>; ++}; ++ ++&dss { ++ status = "okay"; ++ assigned-clocks = <&k3_clks 218 2>, ++ <&k3_clks 218 5>, ++ <&k3_clks 218 14>, ++ <&k3_clks 218 18>; ++ assigned-clock-parents = <&k3_clks 218 3>, ++ <&k3_clks 218 7>, ++ <&k3_clks 218 16>, ++ <&k3_clks 218 22>; ++}; ++ ++&serdes_wiz4 { ++ status = "okay"; ++}; ++ ++&serdes4 { ++ status = "okay"; ++ serdes4_dp_link: phy@0 { ++ reg = <0>; ++ cdns,num-lanes = <4>; ++ #phy-cells = <0>; ++ cdns,phy-type = ; ++ resets = <&serdes_wiz4 1>, <&serdes_wiz4 2>, ++ <&serdes_wiz4 3>, <&serdes_wiz4 4>; ++ }; ++}; ++ ++&mhdp { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&dp0_pins_default>; ++ phys = <&serdes4_dp_link>; ++ phy-names = "dpphy"; ++}; ++ ++&dss_ports { ++ /* DP */ ++ port { ++ dpi0_out: endpoint { ++ remote-endpoint = <&dp0_in>; ++ }; ++ }; ++}; ++ ++&main_i2c4 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&main_i2c4_pins_default>; ++ clock-frequency = <400000>; ++ ++ exp4: gpio@20 { ++ compatible = "ti,tca6408"; ++ reg = <0x20>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ }; ++}; ++ ++&dp0_ports { ++ port@0 { ++ reg = <0>; ++ ++ dp0_in: endpoint { ++ remote-endpoint = <&dpi0_out>; ++ }; ++ }; ++ ++ port@4 { ++ reg = <4>; ++ ++ dp0_out: endpoint { ++ remote-endpoint = <&dp0_connector_in>; ++ }; ++ }; ++}; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,10 +1,25 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for J784S4 SoC Family Main Domain peripherals + * +- * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + ++#include ++#include ++#include ++ ++#include "k3-serdes.h" ++ ++/ { ++ serdes_refclk: clock-serdes { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ /* To be enabled when serdes_wiz* is functional */ ++ status = "disabled"; ++ }; ++}; ++ + &cbass_main { + msmc_ram: sram@70000000 { + compatible = "mmio-sram"; +@@ -26,6 +41,42 @@ + }; + }; + ++ scm_conf: bus@100000 { ++ compatible = "simple-bus"; ++ reg = <0x00 0x00100000 0x00 0x1c000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x00 0x00 0x00100000 0x1c000>; ++ ++ serdes_ln_ctrl: mux-controller@4080 { ++ compatible = "reg-mux"; ++ reg = <0x00004080 0x30>; ++ #mux-control-cells = <1>; ++ mux-reg-masks = <0x0 0x3>, <0x4 0x3>, /* SERDES0 lane0/1 select */ ++ <0x8 0x3>, <0xc 0x3>, /* SERDES0 lane2/3 select */ ++ <0x10 0x3>, <0x14 0x3>, /* SERDES1 lane0/1 select */ ++ <0x18 0x3>, <0x1c 0x3>, /* SERDES1 lane2/3 select */ ++ <0x20 0x3>, <0x24 0x3>, /* SERDES2 lane0/1 select */ ++ <0x28 0x3>, <0x2c 0x3>; /* SERDES2 lane2/3 select */ ++ idle-states = , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ }; ++ }; ++ + gic500: interrupt-controller@1800000 { + compatible = "arm,gic-v3"; + #address-cells = <2>; +@@ -611,6 +662,204 @@ + status = "disabled"; + }; + ++ ti_csi2rx0: ticsi2rx@4500000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ reg = <0x00 0x04500000 0x00 0x00001000>; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dmas = <&main_bcdma_csi 0 0x4940 0>; ++ dma-names = "rx0"; ++ power-domains = <&k3_pds 72 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ cdns_csi2rx0: csi-bridge@4504000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x00 0x04504000 0x00 0x00001000>; ++ clocks = <&k3_clks 72 2>, <&k3_clks 72 0>, <&k3_clks 72 2>, ++ <&k3_clks 72 2>, <&k3_clks 72 3>, <&k3_clks 72 3>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy0>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi0_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi0_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi0_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi0_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi0_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ ti_csi2rx1: ticsi2rx@4510000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ reg = <0x00 0x04510000 0x00 0x1000>; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dmas = <&main_bcdma_csi 0 0x4960 0>; ++ dma-names = "rx0"; ++ power-domains = <&k3_pds 73 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ cdns_csi2rx1: csi-bridge@4514000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x00 0x04514000 0x00 0x00001000>; ++ clocks = <&k3_clks 73 2>, <&k3_clks 73 0>, <&k3_clks 73 2>, ++ <&k3_clks 73 2>, <&k3_clks 73 3>, <&k3_clks 73 3>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy1>; ++ phy-names = "dphy"; ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi1_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi1_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi1_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi1_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi1_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ ti_csi2rx2: ticsi2rx@4520000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ reg = <0x00 0x04520000 0x00 0x00001000>; ++ ranges; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ dmas = <&main_bcdma_csi 0 0x4980 0>; ++ dma-names = "rx0"; ++ power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ cdns_csi2rx2: csi-bridge@4524000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x00 0x04524000 0x00 0x00001000>; ++ clocks = <&k3_clks 74 2>, <&k3_clks 74 0>, <&k3_clks 74 2>, ++ <&k3_clks 74 2>, <&k3_clks 74 3>, <&k3_clks 74 3>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy2>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_port0: port@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ csi2_port1: port@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ csi2_port2: port@2 { ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ csi2_port3: port@3 { ++ reg = <3>; ++ status = "disabled"; ++ }; ++ ++ csi2_port4: port@4 { ++ reg = <4>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ ++ dphy0: phy@4580000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x00 0x04580000 0x00 0x00001100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 212 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ dphy1: phy@4590000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x00 0x04590000 0x00 0x00001100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 213 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ dphy2: phy@45a0000 { ++ compatible = "cdns,dphy-rx"; ++ reg = <0x00 0x045a0000 0x00 0x00001100>; ++ #phy-cells = <0>; ++ power-domains = <&k3_pds 214 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ }; ++ ++ vpu0: video-codec@4210000 { ++ compatible = "ti,j721s2-wave521c", "cnm,wave521c"; ++ reg = <0x00 0x4210000 0x00 0x10000>; ++ interrupts = ; ++ clocks = <&k3_clks 241 2>; ++ power-domains = <&k3_pds 241 TI_SCI_PD_EXCLUSIVE>; ++ }; ++ ++ vpu1: video-codec@4220000 { ++ compatible = "ti,j721s2-wave521c", "cnm,wave521c"; ++ reg = <0x00 0x4220000 0x00 0x10000>; ++ interrupts = ; ++ clocks = <&k3_clks 242 2>; ++ power-domains = <&k3_pds 242 TI_SCI_PD_EXCLUSIVE>; ++ }; ++ + main_sdhci0: mmc@4f80000 { + compatible = "ti,j721e-sdhci-8bit"; + reg = <0x00 0x04f80000 0x00 0x1000>, +@@ -661,6 +910,7 @@ + ti,itap-del-sel-sd-hs = <0x0>; + ti,itap-del-sel-sdr12 = <0x0>; + ti,itap-del-sel-sdr25 = <0x0>; ++ ti,itap-del-sel-ddr50 = <0x2>; + ti,clkbuf-sel = <0x7>; + ti,trm-icp = <0x8>; + dma-coherent; +@@ -669,6 +919,160 @@ + status = "disabled"; + }; + ++ serdes_wiz0: wiz@5060000 { ++ compatible = "ti,j784s4-wiz-10g"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ power-domains = <&k3_pds 404 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 404 2>, <&k3_clks 404 6>, <&serdes_refclk>, <&k3_clks 404 5>; ++ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk"; ++ assigned-clocks = <&k3_clks 404 6>; ++ assigned-clock-parents = <&k3_clks 404 10>; ++ num-lanes = <4>; ++ #reset-cells = <1>; ++ #clock-cells = <1>; ++ ranges = <0x5060000 0x00 0x5060000 0x10000>; ++ status = "disabled"; ++ ++ serdes0: serdes@5060000 { ++ compatible = "ti,j721e-serdes-10g"; ++ reg = <0x05060000 0x010000>; ++ reg-names = "torrent_phy"; ++ resets = <&serdes_wiz0 0>; ++ reset-names = "torrent_reset"; ++ clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>, ++ <&serdes_wiz0 TI_WIZ_PHY_EN_REFCLK>; ++ clock-names = "refclk", "phy_en_refclk"; ++ assigned-clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>, ++ <&serdes_wiz0 TI_WIZ_PLL1_REFCLK>, ++ <&serdes_wiz0 TI_WIZ_REFCLK_DIG>; ++ assigned-clock-parents = <&k3_clks 404 6>, ++ <&k3_clks 404 6>, ++ <&k3_clks 404 6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ status = "disabled"; ++ }; ++ }; ++ ++ serdes_wiz1: wiz@5070000 { ++ compatible = "ti,j784s4-wiz-10g"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ power-domains = <&k3_pds 405 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 405 2>, <&k3_clks 405 6>, <&serdes_refclk>, <&k3_clks 405 5>; ++ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk"; ++ assigned-clocks = <&k3_clks 405 6>; ++ assigned-clock-parents = <&k3_clks 405 10>; ++ num-lanes = <4>; ++ #reset-cells = <1>; ++ #clock-cells = <1>; ++ ranges = <0x05070000 0x00 0x05070000 0x10000>; ++ status = "disabled"; ++ ++ serdes1: serdes@5070000 { ++ compatible = "ti,j721e-serdes-10g"; ++ reg = <0x05070000 0x010000>; ++ reg-names = "torrent_phy"; ++ resets = <&serdes_wiz1 0>; ++ reset-names = "torrent_reset"; ++ clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>, ++ <&serdes_wiz1 TI_WIZ_PHY_EN_REFCLK>; ++ clock-names = "refclk", "phy_en_refclk"; ++ assigned-clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>, ++ <&serdes_wiz1 TI_WIZ_PLL1_REFCLK>, ++ <&serdes_wiz1 TI_WIZ_REFCLK_DIG>; ++ assigned-clock-parents = <&k3_clks 405 6>, ++ <&k3_clks 405 6>, ++ <&k3_clks 405 6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ status = "disabled"; ++ }; ++ }; ++ ++ serdes_wiz2: wiz@5020000 { ++ compatible = "ti,j784s4-wiz-10g"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ power-domains = <&k3_pds 406 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 406 2>, <&k3_clks 406 6>, <&serdes_refclk>, <&k3_clks 406 5>; ++ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk"; ++ assigned-clocks = <&k3_clks 406 6>; ++ assigned-clock-parents = <&k3_clks 406 10>; ++ num-lanes = <4>; ++ #reset-cells = <1>; ++ #clock-cells = <1>; ++ ranges = <0x05020000 0x00 0x05020000 0x10000>; ++ status = "disabled"; ++ ++ serdes2: serdes@5020000 { ++ compatible = "ti,j721e-serdes-10g"; ++ reg = <0x05020000 0x010000>; ++ reg-names = "torrent_phy"; ++ resets = <&serdes_wiz2 0>; ++ reset-names = "torrent_reset"; ++ clocks = <&serdes_wiz2 TI_WIZ_PLL0_REFCLK>, ++ <&serdes_wiz2 TI_WIZ_PHY_EN_REFCLK>; ++ clock-names = "refclk", "phy_en_refclk"; ++ assigned-clocks = <&serdes_wiz2 TI_WIZ_PLL0_REFCLK>, ++ <&serdes_wiz2 TI_WIZ_PLL1_REFCLK>, ++ <&serdes_wiz2 TI_WIZ_REFCLK_DIG>; ++ assigned-clock-parents = <&k3_clks 406 6>, ++ <&k3_clks 406 6>, ++ <&k3_clks 406 6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ status = "disabled"; ++ }; ++ }; ++ ++ serdes_wiz4: wiz@5050000 { ++ compatible = "ti,j784s4-wiz-10g"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ power-domains = <&k3_pds 407 TI_SCI_PD_EXCLUSIVE>; ++ clocks = <&k3_clks 407 2>, <&k3_clks 407 6>, <&serdes_refclk>, <&k3_clks 407 5>; ++ clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk"; ++ assigned-clocks = <&k3_clks 407 6>; ++ assigned-clock-parents = <&k3_clks 407 10>; ++ num-lanes = <4>; ++ #reset-cells = <1>; ++ #clock-cells = <1>; ++ ranges = <0x05050000 0x00 0x05050000 0x10000>, ++ <0xa030a00 0x00 0xa030a00 0x40>; /* DPTX PHY */ ++ status = "disabled"; ++ ++ serdes4: serdes@5050000 { ++ /* ++ * Note: we also map DPTX PHY registers as the Torrent ++ * needs to manage those. ++ */ ++ compatible = "ti,j721e-serdes-10g"; ++ reg = <0x05050000 0x010000>, ++ <0x0a030a00 0x40>; /* DPTX PHY */ ++ reg-names = "torrent_phy"; ++ resets = <&serdes_wiz4 0>; ++ reset-names = "torrent_reset"; ++ clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>, ++ <&serdes_wiz4 TI_WIZ_PHY_EN_REFCLK>; ++ clock-names = "refclk", "phy_en_refclk"; ++ assigned-clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>, ++ <&serdes_wiz4 TI_WIZ_PLL1_REFCLK>, ++ <&serdes_wiz4 TI_WIZ_REFCLK_DIG>; ++ assigned-clock-parents = <&k3_clks 407 6>, ++ <&k3_clks 407 6>, ++ <&k3_clks 407 6>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ #clock-cells = <1>; ++ status = "disabled"; ++ }; ++ }; ++ + main_navss: bus@30000000 { + bootph-all; + compatible = "simple-bus"; +@@ -703,6 +1107,7 @@ + ti,sci = <&sms>; + ti,sci-dev-id = <321>; + ti,interrupt-ranges = <0 0 256>; ++ ti,unmapped-event-sources = <&main_bcdma_csi>; + }; + + secure_proxy_main: mailbox@32c00000 { +@@ -982,8 +1387,12 @@ + compatible = "ti,j721e-navss-main-udmap"; + reg = <0x00 0x31150000 0x00 0x100>, + <0x00 0x34000000 0x00 0x80000>, +- <0x00 0x35000000 0x00 0x200000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x00 0x35000000 0x00 0x200000>, ++ <0x00 0x30b00000 0x00 0x20000>, ++ <0x00 0x30c00000 0x00 0x8000>, ++ <0x00 0x30d00000 0x00 0x4000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&main_udmass_inta>; + #dma-cells = <1>; + +@@ -1000,6 +1409,21 @@ + ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */ + }; + ++ main_bcdma_csi: dma-controller@311a0000 { ++ compatible = "ti,j721s2-dmss-bcdma-csi"; ++ reg = <0x00 0x311a0000 0x00 0x100>, ++ <0x00 0x35d00000 0x00 0x20000>, ++ <0x00 0x35c00000 0x00 0x10000>, ++ <0x00 0x35e00000 0x00 0x80000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt"; ++ msi-parent = <&main_udmass_inta>; ++ #dma-cells = <3>; ++ ti,sci = <&sms>; ++ ti,sci-dev-id = <281>; ++ ti,sci-rm-range-rchan = <0x21>; ++ ti,sci-rm-range-tchan = <0x22>; ++ }; ++ + cpts@310d0000 { + compatible = "ti,j721e-cpts"; + reg = <0x00 0x310d0000 0x00 0x400>; +@@ -1568,4 +1992,279 @@ + firmware-name = "j784s4-c71_3-fw"; + status = "disabled"; + }; ++ ++ main_esm: esm@700000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x700000 0x00 0x1000>; ++ ti,esm-pins = <688>, <689>, <690>, <691>, <692>, <693>, <694>, ++ <695>; ++ bootph-pre-ram; ++ }; ++ ++ watchdog0: watchdog@2200000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2200000 0x00 0x100>; ++ clocks = <&k3_clks 348 1>; ++ power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 348 0>; ++ assigned-clock-parents = <&k3_clks 348 4>; ++ }; ++ ++ watchdog1: watchdog@2210000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2210000 0x00 0x100>; ++ clocks = <&k3_clks 349 1>; ++ power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 349 0>; ++ assigned-clock-parents = <&k3_clks 349 4>; ++ }; ++ ++ watchdog2: watchdog@2220000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2220000 0x00 0x100>; ++ clocks = <&k3_clks 350 1>; ++ power-domains = <&k3_pds 350 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 350 0>; ++ assigned-clock-parents = <&k3_clks 350 4>; ++ }; ++ ++ watchdog3: watchdog@2230000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2230000 0x00 0x100>; ++ clocks = <&k3_clks 351 1>; ++ power-domains = <&k3_pds 351 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 351 0>; ++ assigned-clock-parents = <&k3_clks 351 4>; ++ }; ++ ++ watchdog4: watchdog@2240000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2240000 0x00 0x100>; ++ clocks = <&k3_clks 352 1>; ++ power-domains = <&k3_pds 352 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 352 0>; ++ assigned-clock-parents = <&k3_clks 352 4>; ++ }; ++ ++ watchdog5: watchdog@2250000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2250000 0x00 0x100>; ++ clocks = <&k3_clks 353 1>; ++ power-domains = <&k3_pds 353 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 353 0>; ++ assigned-clock-parents = <&k3_clks 353 4>; ++ }; ++ ++ watchdog6: watchdog@2260000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2260000 0x00 0x100>; ++ clocks = <&k3_clks 354 1>; ++ power-domains = <&k3_pds 354 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 354 0>; ++ assigned-clock-parents = <&k3_clks 354 4>; ++ }; ++ ++ watchdog7: watchdog@2270000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2270000 0x00 0x100>; ++ clocks = <&k3_clks 355 1>; ++ power-domains = <&k3_pds 355 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 355 0>; ++ assigned-clock-parents = <&k3_clks 355 4>; ++ }; ++ ++ /* ++ * The following RTI instances are coupled with MCU R5Fs, c7x and ++ * GPU so keeping them reserved as these will be used by their ++ * respective firmware ++ */ ++ watchdog8: watchdog@22f0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x22f0000 0x00 0x100>; ++ clocks = <&k3_clks 360 1>; ++ power-domains = <&k3_pds 360 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 360 0>; ++ assigned-clock-parents = <&k3_clks 360 4>; ++ /* reserved for GPU */ ++ status = "reserved"; ++ }; ++ ++ watchdog9: watchdog@2300000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2300000 0x00 0x100>; ++ clocks = <&k3_clks 356 1>; ++ power-domains = <&k3_pds 356 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 356 0>; ++ assigned-clock-parents = <&k3_clks 356 4>; ++ /* reserved for C7X_0 DSP */ ++ status = "reserved"; ++ }; ++ ++ watchdog10: watchdog@2310000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2310000 0x00 0x100>; ++ clocks = <&k3_clks 357 1>; ++ power-domains = <&k3_pds 357 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 357 0>; ++ assigned-clock-parents = <&k3_clks 357 4>; ++ /* reserved for C7X_1 DSP */ ++ status = "reserved"; ++ }; ++ ++ watchdog11: watchdog@2320000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2320000 0x00 0x100>; ++ clocks = <&k3_clks 358 1>; ++ power-domains = <&k3_pds 358 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 358 0>; ++ assigned-clock-parents = <&k3_clks 358 4>; ++ /* reserved for C7X_2 DSP */ ++ status = "reserved"; ++ }; ++ ++ watchdog12: watchdog@2330000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2330000 0x00 0x100>; ++ clocks = <&k3_clks 359 1>; ++ power-domains = <&k3_pds 359 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 359 0>; ++ assigned-clock-parents = <&k3_clks 359 4>; ++ /* reserved for C7X_3 DSP */ ++ status = "reserved"; ++ }; ++ ++ watchdog13: watchdog@23c0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x23c0000 0x00 0x100>; ++ clocks = <&k3_clks 361 1>; ++ power-domains = <&k3_pds 361 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 361 0>; ++ assigned-clock-parents = <&k3_clks 361 4>; ++ /* reserved for MAIN_R5F0_0 */ ++ status = "reserved"; ++ }; ++ ++ watchdog14: watchdog@23d0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x23d0000 0x00 0x100>; ++ clocks = <&k3_clks 362 1>; ++ power-domains = <&k3_pds 362 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 362 0>; ++ assigned-clock-parents = <&k3_clks 362 4>; ++ /* reserved for MAIN_R5F0_1 */ ++ status = "reserved"; ++ }; ++ ++ watchdog15: watchdog@23e0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x23e0000 0x00 0x100>; ++ clocks = <&k3_clks 363 1>; ++ power-domains = <&k3_pds 363 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 363 0>; ++ assigned-clock-parents = <&k3_clks 363 4>; ++ /* reserved for MAIN_R5F1_0 */ ++ status = "reserved"; ++ }; ++ ++ watchdog16: watchdog@23f0000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x23f0000 0x00 0x100>; ++ clocks = <&k3_clks 364 1>; ++ power-domains = <&k3_pds 364 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 364 0>; ++ assigned-clock-parents = <&k3_clks 364 4>; ++ /* reserved for MAIN_R5F1_1 */ ++ status = "reserved"; ++ }; ++ ++ watchdog17: watchdog@2540000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2540000 0x00 0x100>; ++ clocks = <&k3_clks 365 1>; ++ power-domains = <&k3_pds 365 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 365 0>; ++ assigned-clock-parents = <&k3_clks 366 4>; ++ /* reserved for MAIN_R5F2_0 */ ++ status = "reserved"; ++ }; ++ ++ watchdog18: watchdog@2550000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x2550000 0x00 0x100>; ++ clocks = <&k3_clks 366 1>; ++ power-domains = <&k3_pds 366 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 366 0>; ++ assigned-clock-parents = <&k3_clks 366 4>; ++ /* reserved for MAIN_R5F2_1 */ ++ status = "reserved"; ++ }; ++ ++ mhdp: bridge@a000000 { ++ compatible = "ti,j721e-mhdp8546"; ++ reg = <0x0 0xa000000 0x0 0x30a00>, ++ <0x0 0x4f40000 0x0 0x20>; ++ reg-names = "mhdptx", "j721e-intg"; ++ clocks = <&k3_clks 217 11>; ++ interrupt-parent = <&gic500>; ++ interrupts = ; ++ power-domains = <&k3_pds 217 TI_SCI_PD_EXCLUSIVE>; ++ status = "disabled"; ++ ++ dp0_ports: ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ /* Remote-endpoints are on the boards so ++ * ports are defined in the platform dt file. ++ */ ++ }; ++ }; ++ ++ dss: dss@4a00000 { ++ compatible = "ti,j721e-dss"; ++ reg = <0x00 0x04a00000 0x00 0x10000>, /* common_m */ ++ <0x00 0x04a10000 0x00 0x10000>, /* common_s0*/ ++ <0x00 0x04b00000 0x00 0x10000>, /* common_s1*/ ++ <0x00 0x04b10000 0x00 0x10000>, /* common_s2*/ ++ <0x00 0x04a20000 0x00 0x10000>, /* vidl1 */ ++ <0x00 0x04a30000 0x00 0x10000>, /* vidl2 */ ++ <0x00 0x04a50000 0x00 0x10000>, /* vid1 */ ++ <0x00 0x04a60000 0x00 0x10000>, /* vid2 */ ++ <0x00 0x04a70000 0x00 0x10000>, /* ovr1 */ ++ <0x00 0x04a90000 0x00 0x10000>, /* ovr2 */ ++ <0x00 0x04ab0000 0x00 0x10000>, /* ovr3 */ ++ <0x00 0x04ad0000 0x00 0x10000>, /* ovr4 */ ++ <0x00 0x04a80000 0x00 0x10000>, /* vp1 */ ++ <0x00 0x04aa0000 0x00 0x10000>, /* vp1 */ ++ <0x00 0x04ac0000 0x00 0x10000>, /* vp1 */ ++ <0x00 0x04ae0000 0x00 0x10000>, /* vp4 */ ++ <0x00 0x04af0000 0x00 0x10000>; /* wb */ ++ reg-names = "common_m", "common_s0", ++ "common_s1", "common_s2", ++ "vidl1", "vidl2","vid1","vid2", ++ "ovr1", "ovr2", "ovr3", "ovr4", ++ "vp1", "vp2", "vp3", "vp4", ++ "wb"; ++ clocks = <&k3_clks 218 0>, ++ <&k3_clks 218 2>, ++ <&k3_clks 218 5>, ++ <&k3_clks 218 14>, ++ <&k3_clks 218 18>; ++ clock-names = "fck", "vp1", "vp2", "vp3", "vp4"; ++ power-domains = <&k3_pds 218 TI_SCI_PD_EXCLUSIVE>; ++ interrupts = , ++ , ++ , ++ ; ++ interrupt-names = "common_m", ++ "common_s0", ++ "common_s1", ++ "common_s2"; ++ status = "disabled"; ++ ++ dss_ports: ports { ++ /* Ports that DSS drives are platform specific ++ * so they are defined in platform dt file. ++ */ ++ }; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,8 +1,8 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT + /* + * Device Tree Source for J784S4 SoC Family MCU/WAKEUP Domain peripherals + * +- * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2022-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + &cbass_mcu_wakeup { +@@ -38,10 +38,18 @@ + }; + }; + +- chipid@43000014 { ++ wkup_conf: bus@43000000 { + bootph-all; +- compatible = "ti,am654-chipid"; +- reg = <0x00 0x43000014 0x00 0x4>; ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0x0 0x00 0x43000000 0x20000>; ++ ++ chipid: chipid@14 { ++ bootph-all; ++ compatible = "ti,am654-chipid"; ++ reg = <0x14 0x4>; ++ }; + }; + + secure_proxy_sa3: mailbox@43600000 { +@@ -478,8 +486,12 @@ + compatible = "ti,j721e-navss-mcu-udmap"; + reg = <0x00 0x285c0000 0x00 0x100>, + <0x00 0x2a800000 0x00 0x40000>, +- <0x00 0x2aa00000 0x00 0x40000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x00 0x2aa00000 0x00 0x40000>, ++ <0x00 0x284a0000 0x00 0x4000>, ++ <0x00 0x284c0000 0x00 0x4000>, ++ <0x00 0x28400000 0x00 0x2000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", ++ "tchan", "rchan", "rflow"; + msi-parent = <&main_udmass_inta>; + #dma-cells = <1>; + +@@ -616,7 +628,7 @@ + compatible = "ti,j7200-vtm"; + reg = <0x00 0x42040000 0x00 0x350>, + <0x00 0x42050000 0x00 0x350>; +- power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>; ++ power-domains = <&k3_pds 243 TI_SCI_PD_SHARED>; + #thermal-sensor-cells = <1>; + }; + +@@ -700,4 +712,44 @@ + status = "disabled"; + }; + }; ++ ++ mcu_esm: esm@40800000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x40800000 0x00 0x1000>; ++ ti,esm-pins = <95>; ++ bootph-pre-ram; ++ }; ++ ++ wkup_esm: esm@42080000 { ++ compatible = "ti,j721e-esm"; ++ reg = <0x00 0x42080000 0x00 0x1000>; ++ ti,esm-pins = <63>; ++ bootph-pre-ram; ++ }; ++ ++ /* ++ * The 2 RTI instances are couple with MCU R5Fs so keeping them ++ * reserved as these will be used by their respective firmware ++ */ ++ mcu_watchdog0: watchdog@40600000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x40600000 0x00 0x100>; ++ clocks = <&k3_clks 367 1>; ++ power-domains = <&k3_pds 367 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 367 0>; ++ assigned-clock-parents = <&k3_clks 367 4>; ++ /* reserved for MCU_R5F0_0 */ ++ status = "reserved"; ++ }; ++ ++ mcu_watchdog1: watchdog@40610000 { ++ compatible = "ti,j7-rti-wdt"; ++ reg = <0x00 0x40610000 0x00 0x100>; ++ clocks = <&k3_clks 368 1>; ++ power-domains = <&k3_pds 368 TI_SCI_PD_EXCLUSIVE>; ++ assigned-clocks = <&k3_clks 368 0>; ++ assigned-clock-parents = <&k3_clks 368 4>; ++ /* reserved for MCU_R5F0_1 */ ++ status = "reserved"; ++ }; + }; +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi +--- a/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi 2024-03-28 11:26:09.897017444 -0400 +@@ -1,4 +1,7 @@ +-// SPDX-License-Identifier: GPL-2.0 ++// SPDX-License-Identifier: GPL-2.0-only OR MIT ++/* ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ ++ */ + + #include + +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-pinctrl.h b/arch/arm64/boot/dts/ti/k3-pinctrl.h +--- a/arch/arm64/boot/dts/ti/k3-pinctrl.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-pinctrl.h 2024-03-28 11:26:09.897017444 -0400 +@@ -1,9 +1,9 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + /* + * This header provides constants for pinctrl bindings for TI's K3 SoC + * family. + * +- * Copyright (C) 2018-2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + #ifndef DTS_ARM64_TI_K3_PINCTRL_H + #define DTS_ARM64_TI_K3_PINCTRL_H +@@ -59,6 +59,9 @@ + #define J721S2_IOPAD(pa, val, muxmode) (((pa) & 0x1fff)) ((val) | (muxmode)) + #define J721S2_WKUP_IOPAD(pa, val, muxmode) (((pa) & 0x1fff)) ((val) | (muxmode)) + ++#define J722S_IOPAD(pa, val, muxmode) (((pa) & 0x1fff)) ((val) | (muxmode)) ++#define J722S_MCU_IOPAD(pa, val, muxmode) (((pa) & 0x1fff)) ((val) | (muxmode)) ++ + #define J784S4_IOPAD(pa, val, muxmode) (((pa) & 0x1fff)) ((val) | (muxmode)) + #define J784S4_WKUP_IOPAD(pa, val, muxmode) (((pa) & 0x1fff)) ((val) | (muxmode)) + +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-serdes.h b/arch/arm64/boot/dts/ti/k3-serdes.h +--- a/arch/arm64/boot/dts/ti/k3-serdes.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/k3-serdes.h 2024-03-28 11:26:09.897017444 -0400 +@@ -1,8 +1,8 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + /* + * This header provides constants for SERDES MUX for TI SoCs + * +- * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * Copyright (C) 2023-2024 Texas Instruments Incorporated - https://www.ti.com/ + */ + + #ifndef DTS_ARM64_TI_K3_SERDES_H +@@ -111,7 +111,7 @@ + + #define J721S2_SERDES0_LANE2_EDP_LANE2 0x0 + #define J721S2_SERDES0_LANE2_PCIE1_LANE2 0x1 +-#define J721S2_SERDES0_LANE2_IP3_UNUSED 0x2 ++#define J721S2_SERDES0_LANE2_USB_SWAP 0x2 + #define J721S2_SERDES0_LANE2_IP4_UNUSED 0x3 + + #define J721S2_SERDES0_LANE3_EDP_LANE3 0x0 +diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile +--- a/arch/arm64/boot/dts/ti/Makefile 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/boot/dts/ti/Makefile 2024-03-28 11:26:09.893017428 -0400 +@@ -9,20 +9,21 @@ + # alphabetically. + + # Boards with AM62x SoC +-k3-am625-sk-hdmi-audio-dtbs := k3-am625-sk.dtb k3-am62x-sk-hdmi-audio.dtbo +-k3-am62-lp-sk-hdmi-audio-dtbs := k3-am62-lp-sk.dtb k3-am62x-sk-hdmi-audio.dtbo + dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay-csi2-ov5640.dtbo ++dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay-csi2-tevi-ov5640.dtbo + dtb-$(CONFIG_ARCH_K3) += k3-am625-phyboard-lyra-rdk.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am625-sk.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-dahlia.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-dev.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-mallow.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-nonwifi-yavia.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-dahlia.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-dev.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-mallow.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am625-verdin-wifi-yavia.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-am62x-phyboard-lyra-gpio-fan.dtbo + dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk.dtb +-dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-hdmi-audio.dtb +-dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk-hdmi-audio.dtb + + # Boards with AM62Ax SoC + dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk.dtb +@@ -30,22 +31,26 @@ + # Boards with AM62Px SoC + dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk.dtb + ++# Common overlays for SK-AM62* family of boards ++dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-csi2-ov5640.dtbo ++dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-csi2-tevi-ov5640.dtbo ++dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-csi2-imx219.dtbo ++dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-hdmi-audio.dtbo ++ + # Boards with AM64x SoC + dtb-$(CONFIG_ARCH_K3) += k3-am642-evm.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am642-phyboard-electra-rdk.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am642-sk.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am642-tqma64xxl-mbax4xxl.dtb +- +-k3-am642-tqma64xxl-mbax4xxl-sdcard-dtbs := \ +- k3-am642-tqma64xxl-mbax4xxl.dtb k3-am64-tqma64xxl-mbax4xxl-sdcard.dtbo +-k3-am642-tqma64xxl-mbax4xxl-wlan-dtbs := \ +- k3-am642-tqma64xxl-mbax4xxl.dtb k3-am64-tqma64xxl-mbax4xxl-wlan.dtbo +- +-dtb-$(CONFIG_ARCH_K3) += k3-am642-tqma64xxl-mbax4xxl-sdcard.dtb +-dtb-$(CONFIG_ARCH_K3) += k3-am642-tqma64xxl-mbax4xxl-wlan.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-am64-tqma64xxl-mbax4xxl-sdcard.dtbo ++dtb-$(CONFIG_ARCH_K3) += k3-am64-tqma64xxl-mbax4xxl-wlan.dtbo + + # Boards with AM65x SoC +-k3-am654-gp-evm-dtbs := k3-am654-base-board.dtb k3-am654-base-board-rocktech-rk101-panel.dtbo ++k3-am654-gp-evm-dtbs := k3-am654-base-board.dtb \ ++ k3-am654-base-board-rocktech-rk101-panel.dtbo \ ++ k3-am654-pcie-usb3.dtbo ++k3-am654-evm-dtbs := k3-am654-base-board.dtb k3-am654-icssg2.dtbo ++k3-am654-idk-dtbs := k3-am654-evm.dtb k3-am654-idk.dtbo k3-am654-pcie-usb2.dtbo + dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic-pg2.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced.dtb +@@ -53,6 +58,11 @@ + dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-pg2.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board.dtb + dtb-$(CONFIG_ARCH_K3) += k3-am654-gp-evm.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-am654-evm.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-am654-idk.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board-rocktech-rk101-panel.dtbo ++dtb-$(CONFIG_ARCH_K3) += k3-am654-pcie-usb2.dtbo ++dtb-$(CONFIG_ARCH_K3) += k3-am654-pcie-usb3.dtbo + + # Boards with J7200 SoC + k3-j7200-evm-dtbs := k3-j7200-common-proc-board.dtb k3-j7200-evm-quad-port-eth-exp.dtbo +@@ -63,7 +73,9 @@ + dtb-$(CONFIG_ARCH_K3) += k3-j721e-beagleboneai64.dtb + dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm.dtb + dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-gesi-exp-board.dtbo ++dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-pcie0-ep.dtbo + dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk-csi2-dual-imx219.dtbo + + # Boards with J721s2 SoC + dtb-$(CONFIG_ARCH_K3) += k3-am68-sk-base-board.dtb +@@ -71,14 +83,78 @@ + dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-gesi-exp-board.dtbo + k3-j721s2-evm-dtbs := k3-j721s2-common-proc-board.dtb k3-j721s2-evm-gesi-exp-board.dtbo + dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm.dtb ++dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-pcie1-ep.dtbo ++ ++# Boards with J722s SoC ++dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm.dtb + + # Boards with J784s4 SoC + dtb-$(CONFIG_ARCH_K3) += k3-am69-sk.dtb + dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm.dtb + ++# Build time test only, enabled by CONFIG_OF_ALL_DTBS ++k3-am625-beagleplay-csi2-ov5640-dtbs := k3-am625-beagleplay.dtb \ ++ k3-am625-beagleplay-csi2-ov5640.dtbo ++k3-am625-beagleplay-csi2-tevi-ov5640-dtbs := k3-am625-beagleplay.dtb \ ++ k3-am625-beagleplay-csi2-tevi-ov5640.dtbo ++k3-am625-phyboard-lyra-gpio-fan-dtbs := k3-am625-phyboard-lyra-rdk.dtb \ ++ k3-am62x-phyboard-lyra-gpio-fan.dtbo ++k3-am625-sk-csi2-imx219-dtbs := k3-am625-sk.dtb \ ++ k3-am62x-sk-csi2-imx219.dtbo ++k3-am625-sk-csi2-ov5640-dtbs := k3-am625-sk.dtb \ ++ k3-am62x-sk-csi2-ov5640.dtbo ++k3-am625-sk-csi2-tevi-ov5640-dtbs := k3-am625-sk.dtb \ ++ k3-am62x-sk-csi2-tevi-ov5640.dtbo ++k3-am625-sk-hdmi-audio-dtbs := k3-am625-sk.dtb k3-am62x-sk-hdmi-audio.dtbo ++k3-am62-lp-sk-hdmi-audio-dtbs := k3-am62-lp-sk.dtb k3-am62x-sk-hdmi-audio.dtbo ++k3-am62a7-sk-csi2-imx219-dtbs := k3-am62a7-sk.dtb \ ++ k3-am62x-sk-csi2-imx219.dtbo ++k3-am62a7-sk-csi2-ov5640-dtbs := k3-am62a7-sk.dtb \ ++ k3-am62x-sk-csi2-ov5640.dtbo ++k3-am62a7-sk-csi2-tevi-ov5640-dtbs := k3-am62a7-sk.dtb \ ++ k3-am62x-sk-csi2-tevi-ov5640.dtbo ++k3-am62a7-sk-hdmi-audio-dtbs := k3-am62a7-sk.dtb k3-am62x-sk-hdmi-audio.dtbo ++k3-am642-tqma64xxl-mbax4xxl-sdcard-dtbs := \ ++ k3-am642-tqma64xxl-mbax4xxl.dtb k3-am64-tqma64xxl-mbax4xxl-sdcard.dtbo ++k3-am642-tqma64xxl-mbax4xxl-wlan-dtbs := \ ++ k3-am642-tqma64xxl-mbax4xxl.dtb k3-am64-tqma64xxl-mbax4xxl-wlan.dtbo ++k3-am68-sk-base-board-csi2-dual-imx219-dtbs := k3-am68-sk-base-board.dtb \ ++ k3-j721e-sk-csi2-dual-imx219.dtbo ++k3-am69-sk-csi2-dual-imx219-dtbs := k3-am69-sk.dtb \ ++ k3-j721e-sk-csi2-dual-imx219.dtbo ++k3-j721e-evm-pcie0-ep-dtbs := k3-j721e-common-proc-board.dtb \ ++ k3-j721e-evm-pcie0-ep.dtbo ++k3-j721e-sk-csi2-dual-imx219-dtbs := k3-j721e-sk.dtb \ ++ k3-j721e-sk-csi2-dual-imx219.dtbo ++k3-j721s2-evm-pcie1-ep-dtbs := k3-j721s2-common-proc-board.dtb \ ++ k3-j721s2-evm-pcie1-ep.dtbo ++dtb- += k3-am625-beagleplay-csi2-ov5640.dtb \ ++ k3-am625-beagleplay-csi2-tevi-ov5640.dtb \ ++ k3-am625-sk-csi2-imx219.dtb \ ++ k3-am625-sk-csi2-ov5640.dtb \ ++ k3-am625-sk-csi2-tevi-ov5640.dtb \ ++ k3-am625-sk-hdmi-audio.dtb \ ++ k3-am62-lp-sk-hdmi-audio.dtb \ ++ k3-am62a7-sk-csi2-imx219.dtb \ ++ k3-am62a7-sk-csi2-ov5640.dtb \ ++ k3-am62a7-sk-hdmi-audio.dtb \ ++ k3-am642-tqma64xxl-mbax4xxl-sdcard.dtb \ ++ k3-am642-tqma64xxl-mbax4xxl-wlan.dtb \ ++ k3-am68-sk-base-board-csi2-dual-imx219-dtbs \ ++ k3-am69-sk-csi2-dual-imx219-dtbs \ ++ k3-j721e-evm-pcie0-ep.dtb \ ++ k3-j721e-sk-csi2-dual-imx219-dtbs \ ++ k3-j721s2-evm-pcie1-ep.dtb ++ + # Enable support for device-tree overlays ++DTC_FLAGS_k3-am625-beagleplay += -@ + DTC_FLAGS_k3-am625-sk += -@ + DTC_FLAGS_k3-am62-lp-sk += -@ ++DTC_FLAGS_k3-am62a7-sk += -@ ++DTC_FLAGS_k3-am642-tqma64xxl-mbax4xxl += -@ + DTC_FLAGS_k3-am6548-iot2050-advanced-m2 += -@ ++DTC_FLAGS_k3-am68-sk-base-board += -@ ++DTC_FLAGS_k3-am69-sk += -@ + DTC_FLAGS_k3-j721e-common-proc-board += -@ ++DTC_FLAGS_k3-j721e-sk += -@ + DTC_FLAGS_k3-j721s2-common-proc-board += -@ +diff -Naur --no-dereference a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig +--- a/arch/arm64/configs/defconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/arch/arm64/configs/defconfig 2024-03-28 11:26:09.897017444 -0400 +@@ -368,6 +368,7 @@ + CONFIG_STMMAC_ETH=m + CONFIG_DWMAC_TEGRA=m + CONFIG_TI_K3_AM65_CPSW_NUSS=y ++CONFIG_TI_ICSSG_PRUETH=m + CONFIG_QCOM_IPA=m + CONFIG_MESON_GXL_PHY=m + CONFIG_AQUANTIA_PHY=y +@@ -447,6 +448,7 @@ + CONFIG_LEGACY_PTY_COUNT=16 + CONFIG_SERIAL_8250=y + CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=8 + CONFIG_SERIAL_8250_EXTENDED=y + CONFIG_SERIAL_8250_SHARE_IRQ=y + CONFIG_SERIAL_8250_BCM2835AUX=y +@@ -722,6 +724,7 @@ + CONFIG_MFD_SL28CPLD=y + CONFIG_RZ_MTU3=y + CONFIG_MFD_TPS65219=y ++CONFIG_MFD_TPS6594_I2C=m + CONFIG_MFD_TI_AM335X_TSCADC=m + CONFIG_MFD_ROHM_BD718XX=y + CONFIG_MFD_WCD934X=m +@@ -774,6 +777,7 @@ + CONFIG_V4L_PLATFORM_DRIVERS=y + CONFIG_SDR_PLATFORM_DRIVERS=y + CONFIG_V4L_MEM2MEM_DRIVERS=y ++CONFIG_VIDEO_CADENCE_CSI2RX=m + CONFIG_VIDEO_MEDIATEK_JPEG=m + CONFIG_VIDEO_MEDIATEK_VCODEC=m + CONFIG_VIDEO_IMX7_CSI=m +@@ -795,6 +799,7 @@ + CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m + CONFIG_VIDEO_SAMSUNG_S5P_MFC=m + CONFIG_VIDEO_SUN6I_CSI=m ++CONFIG_VIDEO_TI_J721E_CSI2RX=m + CONFIG_VIDEO_HANTRO=m + CONFIG_VIDEO_IMX219=m + CONFIG_VIDEO_IMX412=m +@@ -1403,6 +1408,7 @@ + CONFIG_PHY_CAN_TRANSCEIVER=m + CONFIG_PHY_SUN4I_USB=y + CONFIG_PHY_CADENCE_TORRENT=m ++CONFIG_PHY_CADENCE_DPHY_RX=m + CONFIG_PHY_CADENCE_SIERRA=m + CONFIG_PHY_MIXEL_MIPI_DPHY=m + CONFIG_PHY_FSL_IMX8M_PCIE=y +diff -Naur --no-dereference a/Documentation/devicetree/bindings/arm/ti/k3.yaml b/Documentation/devicetree/bindings/arm/ti/k3.yaml +--- a/Documentation/devicetree/bindings/arm/ti/k3.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/arm/ti/k3.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -50,6 +50,7 @@ + - enum: + - toradex,verdin-am62-nonwifi-dahlia # Verdin AM62 Module on Dahlia + - toradex,verdin-am62-nonwifi-dev # Verdin AM62 Module on Verdin Development Board ++ - toradex,verdin-am62-nonwifi-mallow # Verdin AM62 Module on Mallow + - toradex,verdin-am62-nonwifi-yavia # Verdin AM62 Module on Yavia + - const: toradex,verdin-am62-nonwifi # Verdin AM62 Module without Wi-Fi / BT + - const: toradex,verdin-am62 # Verdin AM62 Module +@@ -60,6 +61,7 @@ + - enum: + - toradex,verdin-am62-wifi-dahlia # Verdin AM62 Wi-Fi / BT Module on Dahlia + - toradex,verdin-am62-wifi-dev # Verdin AM62 Wi-Fi / BT M. on Verdin Development B. ++ - toradex,verdin-am62-wifi-mallow # Verdin AM62 Wi-Fi / BT Module on Mallow + - toradex,verdin-am62-wifi-yavia # Verdin AM62 Wi-Fi / BT Module on Yavia + - const: toradex,verdin-am62-wifi # Verdin AM62 Wi-Fi / BT Module + - const: toradex,verdin-am62 # Verdin AM62 Module +@@ -121,6 +123,12 @@ + - ti,j721s2-evm + - const: ti,j721s2 + ++ - description: K3 J722S SoC and Boards ++ items: ++ - enum: ++ - ti,j722s-evm ++ - const: ti,j722s ++ + - description: K3 J784s4 SoC + items: + - enum: +diff -Naur --no-dereference a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml +--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -23,6 +23,7 @@ + compatible: + enum: + - ti,am625-dss ++ - ti,am62a7,dss + - ti,am65x-dss + + reg: +@@ -36,6 +37,7 @@ + - description: OVR2 overlay manager for vp2 + - description: VP1 video port 1 + - description: VP2 video port 2 ++ - description: common1 DSS register area + + reg-names: + items: +@@ -46,6 +48,7 @@ + - const: ovr2 + - const: vp1 + - const: vp2 ++ - const: common1 + + clocks: + items: +@@ -87,6 +90,7 @@ + For AM65x DSS, the OLDI output port node from video port 1. + For AM625 DSS, the internal DPI output port node from video + port 1. ++ For AM62A7 DSS, the port is tied off inside the SoC. + + port@1: + $ref: /schemas/graph.yaml#/properties/port +@@ -108,6 +112,18 @@ + Input memory (from main memory to dispc) bandwidth limit in + bytes per second + ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: ti,am62a7-dss ++ then: ++ properties: ++ ports: ++ properties: ++ port@0: false ++ + required: + - compatible + - reg +@@ -133,9 +149,10 @@ + <0x04a07000 0x1000>, /* ovr1 */ + <0x04a08000 0x1000>, /* ovr2 */ + <0x04a0a000 0x1000>, /* vp1 */ +- <0x04a0b000 0x1000>; /* vp2 */ ++ <0x04a0b000 0x1000>, /* vp2 */ ++ <0x04a01000 0x1000>; /* common1 */ + reg-names = "common", "vidl1", "vid", +- "ovr1", "ovr2", "vp1", "vp2"; ++ "ovr1", "ovr2", "vp1", "vp2", "common1"; + ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>; + power-domains = <&k3_pds 67 TI_SCI_PD_EXCLUSIVE>; + clocks = <&k3_clks 67 1>, +diff -Naur --no-dereference a/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml b/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml +--- a/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -37,11 +37,11 @@ + + reg: + minItems: 3 +- maxItems: 5 ++ maxItems: 9 + + reg-names: + minItems: 3 +- maxItems: 5 ++ maxItems: 9 + + "#dma-cells": + const: 3 +@@ -141,7 +141,10 @@ + ti,sci-rm-range-tchan: false + + reg: +- maxItems: 3 ++ items: ++ - description: BCDMA Control /Status Registers region ++ - description: RX Channel Realtime Registers region ++ - description: Ring Realtime Registers region + + reg-names: + items: +@@ -161,14 +164,29 @@ + properties: + reg: + minItems: 5 ++ items: ++ - description: BCDMA Control /Status Registers region ++ - description: Block Copy Channel Realtime Registers region ++ - description: RX Channel Realtime Registers region ++ - description: TX Channel Realtime Registers region ++ - description: Ring Realtime Registers region ++ - description: Ring Configuration Registers region ++ - description: TX Channel Configuration Registers region ++ - description: RX Channel Configuration Registers region ++ - description: Block Copy Channel Configuration Registers region + + reg-names: ++ minItems: 5 + items: + - const: gcfg + - const: bchanrt + - const: rchanrt + - const: tchanrt + - const: ringrt ++ - const: ring ++ - const: tchan ++ - const: rchan ++ - const: bchan + + required: + - ti,sci-rm-range-bchan +@@ -184,7 +202,11 @@ + ti,sci-rm-range-bchan: false + + reg: +- maxItems: 4 ++ items: ++ - description: BCDMA Control /Status Registers region ++ - description: RX Channel Realtime Registers region ++ - description: TX Channel Realtime Registers region ++ - description: Ring Realtime Registers region + + reg-names: + items: +@@ -220,8 +242,13 @@ + <0x0 0x4c000000 0x0 0x20000>, + <0x0 0x4a820000 0x0 0x20000>, + <0x0 0x4aa40000 0x0 0x20000>, +- <0x0 0x4bc00000 0x0 0x100000>; +- reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt"; ++ <0x0 0x4bc00000 0x0 0x100000>, ++ <0x0 0x48600000 0x0 0x8000>, ++ <0x0 0x484a4000 0x0 0x2000>, ++ <0x0 0x484c2000 0x0 0x2000>, ++ <0x0 0x48420000 0x0 0x2000>; ++ reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "bchan"; + msi-parent = <&inta_main_dmss>; + #dma-cells = <3>; + +diff -Naur --no-dereference a/Documentation/devicetree/bindings/dma/ti/k3-pktdma.yaml b/Documentation/devicetree/bindings/dma/ti/k3-pktdma.yaml +--- a/Documentation/devicetree/bindings/dma/ti/k3-pktdma.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/dma/ti/k3-pktdma.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -45,14 +45,28 @@ + The second cell is the ASEL value for the channel + + reg: +- maxItems: 4 ++ minItems: 4 ++ items: ++ - description: Packet DMA Control /Status Registers region ++ - description: RX Channel Realtime Registers region ++ - description: TX Channel Realtime Registers region ++ - description: Ring Realtime Registers region ++ - description: Ring Configuration Registers region ++ - description: TX Configuration Registers region ++ - description: RX Configuration Registers region ++ - description: RX Flow Configuration Registers region + + reg-names: ++ minItems: 4 + items: + - const: gcfg + - const: rchanrt + - const: tchanrt + - const: ringrt ++ - const: ring ++ - const: tchan ++ - const: rchan ++ - const: rflow + + msi-parent: true + +@@ -136,8 +150,14 @@ + reg = <0x0 0x485c0000 0x0 0x100>, + <0x0 0x4a800000 0x0 0x20000>, + <0x0 0x4aa00000 0x0 0x40000>, +- <0x0 0x4b800000 0x0 0x400000>; +- reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt"; ++ <0x0 0x4b800000 0x0 0x400000>, ++ <0x0 0x485e0000 0x0 0x20000>, ++ <0x0 0x484a0000 0x0 0x4000>, ++ <0x0 0x484c0000 0x0 0x2000>, ++ <0x0 0x48430000 0x0 0x4000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt", ++ "ring", "tchan", "rchan", "rflow"; ++ + msi-parent = <&inta_main_dmss>; + #dma-cells = <2>; + +diff -Naur --no-dereference a/Documentation/devicetree/bindings/dma/ti/k3-udma.yaml b/Documentation/devicetree/bindings/dma/ti/k3-udma.yaml +--- a/Documentation/devicetree/bindings/dma/ti/k3-udma.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/dma/ti/k3-udma.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -69,13 +69,24 @@ + - ti,j721e-navss-mcu-udmap + + reg: +- maxItems: 3 ++ minItems: 3 ++ items: ++ - description: UDMA-P Control /Status Registers region ++ - description: RX Channel Realtime Registers region ++ - description: TX Channel Realtime Registers region ++ - description: TX Configuration Registers region ++ - description: RX Configuration Registers region ++ - description: RX Flow Configuration Registers region + + reg-names: ++ minItems: 3 + items: + - const: gcfg + - const: rchanrt + - const: tchanrt ++ - const: tchan ++ - const: rchan ++ - const: rflow + + msi-parent: true + +@@ -158,8 +169,11 @@ + compatible = "ti,am654-navss-main-udmap"; + reg = <0x0 0x31150000 0x0 0x100>, + <0x0 0x34000000 0x0 0x100000>, +- <0x0 0x35000000 0x0 0x100000>; +- reg-names = "gcfg", "rchanrt", "tchanrt"; ++ <0x0 0x35000000 0x0 0x100000>, ++ <0x0 0x30b00000 0x0 0x20000>, ++ <0x0 0x30c00000 0x0 0x8000>, ++ <0x0 0x30d00000 0x0 0x4000>; ++ reg-names = "gcfg", "rchanrt", "tchanrt", "tchan", "rchan", "rflow"; + #dma-cells = <1>; + + ti,ringacc = <&ringacc>; +diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml +--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -18,6 +18,7 @@ + items: + - enum: + - starfive,jh7110-csi2rx ++ - ti,j721e-csi2rx + - const: cdns,csi2rx + + reg: +diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/cnm,wave521c.yaml b/Documentation/devicetree/bindings/media/cnm,wave521c.yaml +--- a/Documentation/devicetree/bindings/media/cnm,wave521c.yaml 1969-12-31 19:00:00.000000000 -0500 ++++ b/Documentation/devicetree/bindings/media/cnm,wave521c.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,61 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/cnm,wave521c.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Chips&Media Wave 5 Series multi-standard codec IP ++ ++maintainers: ++ - Nas Chung ++ - Jackson Lee ++ ++description: ++ The Chips&Media WAVE codec IP is a multi format video encoder/decoder ++ ++properties: ++ compatible: ++ items: ++ - enum: ++ - ti,j721s2-wave521c ++ - const: cnm,wave521c ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: VCODEC clock ++ ++ interrupts: ++ maxItems: 1 ++ ++ power-domains: ++ maxItems: 1 ++ ++ resets: ++ maxItems: 1 ++ ++ sram: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ The VPU uses the SRAM to store some of the reference data instead of ++ storing it on DMA memory. It is mainly used for the purpose of reducing ++ bandwidth. ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ ++additionalProperties: false ++ ++examples: ++ - | ++ vpu: video-codec@12345678 { ++ compatible = "ti,j721s2-wave521c", "cnm,wave521c"; ++ reg = <0x12345678 0x1000>; ++ clocks = <&clks 42>; ++ interrupts = <42>; ++ sram = <&sram>; ++ }; +diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml +--- a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml 1969-12-31 19:00:00.000000000 -0500 ++++ b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx-shim.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,100 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/ti,j721e-csi2rx-shim.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: TI J721E CSI2RX Shim ++ ++description: | ++ The TI J721E CSI2RX Shim is a wrapper around Cadence CSI2RX bridge that ++ enables sending captured frames to memory over PSI-L DMA. In the J721E ++ Technical Reference Manual (SPRUIL1B) it is referred to as "SHIM" under the ++ CSI_RX_IF section. ++ ++maintainers: ++ - Jai Luthra ++ ++properties: ++ compatible: ++ const: ti,j721e-csi2rx-shim ++ ++ dmas: ++ maxItems: 1 ++ ++ dma-names: ++ items: ++ - const: rx0 ++ ++ reg: ++ maxItems: 1 ++ ++ power-domains: ++ maxItems: 1 ++ ++ ranges: true ++ ++ "#address-cells": true ++ ++ "#size-cells": true ++ ++patternProperties: ++ "^csi-bridge@": ++ type: object ++ description: CSI2 bridge node. ++ $ref: cdns,csi2rx.yaml# ++ ++required: ++ - compatible ++ - reg ++ - dmas ++ - dma-names ++ - power-domains ++ - ranges ++ - "#address-cells" ++ - "#size-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ ti_csi2rx0: ticsi2rx@4500000 { ++ compatible = "ti,j721e-csi2rx-shim"; ++ dmas = <&main_udmap 0x4940>; ++ dma-names = "rx0"; ++ reg = <0x4500000 0x1000>; ++ power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ ++ cdns_csi2rx: csi-bridge@4504000 { ++ compatible = "ti,j721e-csi2rx", "cdns,csi2rx"; ++ reg = <0x4504000 0x1000>; ++ clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>, ++ <&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>; ++ clock-names = "sys_clk", "p_clk", "pixel_if0_clk", ++ "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk"; ++ phys = <&dphy0>; ++ phy-names = "dphy"; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ csi2_0: port@0 { ++ ++ reg = <0>; ++ ++ csi2rx0_in_sensor: endpoint { ++ remote-endpoint = <&csi2_cam0>; ++ bus-type = <4>; /* CSI2 DPHY. */ ++ clock-lanes = <0>; ++ data-lanes = <1 2>; ++ }; ++ }; ++ }; ++ }; ++ }; +diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml +--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -160,6 +160,7 @@ + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 8 ++ uniqueItems: true + items: + # Assume up to 9 physical lane indices + maximum: 8 +diff -Naur --no-dereference a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentation/devicetree/bindings/mfd/syscon.yaml +--- a/Documentation/devicetree/bindings/mfd/syscon.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/mfd/syscon.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -69,6 +69,8 @@ + - rockchip,rk3588-qos + - rockchip,rv1126-qos + - starfive,jh7100-sysmain ++ - ti,am654-dss-oldi-io-ctrl ++ - ti,j784s4-pcie-ctrl + + - const: syscon + +diff -Naur --no-dereference a/Documentation/devicetree/bindings/mfd/ti,am3359-tscadc.yaml b/Documentation/devicetree/bindings/mfd/ti,am3359-tscadc.yaml +--- a/Documentation/devicetree/bindings/mfd/ti,am3359-tscadc.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/mfd/ti,am3359-tscadc.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -61,8 +61,6 @@ + - interrupts + - clocks + - clock-names +- - dmas +- - dma-names + + additionalProperties: false + +diff -Naur --no-dereference a/Documentation/devicetree/bindings/net/ti,cc1352p7.yaml b/Documentation/devicetree/bindings/net/ti,cc1352p7.yaml +--- a/Documentation/devicetree/bindings/net/ti,cc1352p7.yaml 1969-12-31 19:00:00.000000000 -0500 ++++ b/Documentation/devicetree/bindings/net/ti,cc1352p7.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,51 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/ti,cc1352p7.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Texas Instruments Simplelink CC1352P7 wireless MCU ++ ++description: ++ The CC1352P7 MCU can be connected via SPI or UART. ++ ++maintainers: ++ - Ayush Singh ++ ++properties: ++ compatible: ++ const: ti,cc1352p7 ++ ++ clocks: ++ items: ++ - description: high-frequency main system (MCU and peripherals) clock ++ - description: low-frequency system clock ++ ++ clock-names: ++ items: ++ - const: sclk_hf ++ - const: sclk_lf ++ ++ reset-gpios: ++ maxItems: 1 ++ ++ vdds-supply: true ++ ++required: ++ - compatible ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ serial { ++ mcu { ++ compatible = "ti,cc1352p7"; ++ clocks = <&sclk_hf 0>, <&sclk_lf 25>; ++ clock-names = "sclk_hf", "sclk_lf"; ++ reset-gpios = <&pio 35 GPIO_ACTIVE_LOW>; ++ vdds-supply = <&vdds>; ++ }; ++ }; +diff -Naur --no-dereference a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml +--- a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -19,6 +19,7 @@ + properties: + compatible: + enum: ++ - ti,am642-icssg-prueth # for AM64x SoC family + - ti,am654-icssg-prueth # for AM65x SoC family + + sram: +@@ -106,6 +107,13 @@ + phandle to system controller node and register offset + to ICSSG control register for RGMII transmit delay + ++ ti,half-duplex-capable: ++ type: boolean ++ description: ++ Indicates that the PHY output pin COL is routed to ICSSG GPIO pin ++ (PRGx_PRU0/1_GPIO10) as input so that the ICSSG MII port is ++ capable of half duplex operations. ++ + required: + - reg + anyOf: +diff -Naur --no-dereference a/Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml b/Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml +--- a/Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -10,13 +10,11 @@ + maintainers: + - Kishon Vijay Abraham I + +-allOf: +- - $ref: cdns-pcie-ep.yaml# +- + properties: + compatible: + oneOf: + - const: ti,j721e-pcie-ep ++ - const: ti,j784s4-pcie-ep + - description: PCIe EP controller in AM64 + items: + - const: ti,am64-pcie-ep +@@ -65,6 +63,41 @@ + items: + - const: link_state + ++allOf: ++ - $ref: cdns-pcie-ep.yaml# ++ - if: ++ properties: ++ compatible: ++ enum: ++ - ti,am64-pcie-ep ++ then: ++ properties: ++ num-lanes: ++ const: 1 ++ ++ - if: ++ properties: ++ compatible: ++ enum: ++ - ti,j7200-pcie-ep ++ - ti,j721e-pcie-ep ++ then: ++ properties: ++ num-lanes: ++ minimum: 1 ++ maximum: 2 ++ ++ - if: ++ properties: ++ compatible: ++ enum: ++ - ti,j784s4-pcie-ep ++ then: ++ properties: ++ num-lanes: ++ minimum: 1 ++ maximum: 4 ++ + required: + - compatible + - reg +diff -Naur --no-dereference a/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml b/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml +--- a/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -10,13 +10,11 @@ + maintainers: + - Kishon Vijay Abraham I + +-allOf: +- - $ref: cdns-pcie-host.yaml# +- + properties: + compatible: + oneOf: + - const: ti,j721e-pcie-host ++ - const: ti,j784s4-pcie-host + - description: PCIe controller in AM64 + items: + - const: ti,am64-pcie-host +@@ -94,6 +92,41 @@ + interrupts: + maxItems: 1 + ++allOf: ++ - $ref: cdns-pcie-host.yaml# ++ - if: ++ properties: ++ compatible: ++ enum: ++ - ti,am64-pcie-host ++ then: ++ properties: ++ num-lanes: ++ const: 1 ++ ++ - if: ++ properties: ++ compatible: ++ enum: ++ - ti,j7200-pcie-host ++ - ti,j721e-pcie-host ++ then: ++ properties: ++ num-lanes: ++ minimum: 1 ++ maximum: 2 ++ ++ - if: ++ properties: ++ compatible: ++ enum: ++ - ti,j784s4-pcie-host ++ then: ++ properties: ++ num-lanes: ++ minimum: 1 ++ maximum: 4 ++ + required: + - compatible + - reg +diff -Naur --no-dereference a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml +--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -31,6 +31,7 @@ + - ti,omap3-padconf + - ti,omap4-padconf + - ti,omap5-padconf ++ - ti,j7200-padconf + - const: pinctrl-single + + reg: +diff -Naur --no-dereference a/Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml +--- a/Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/remoteproc/ti,pru-rproc.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -66,6 +66,17 @@ + Should contain the name of the default firmware image + file located on the firmware search path. + ++ interrupts: ++ maxItems: 1 ++ description: ++ Interrupt specifiers enable the virtio/rpmsg communication between MPU ++ and the PRU/RTU cores. For the values of the interrupt cells please refer ++ to interrupt-controller/ti,pruss-intc.yaml schema. ++ ++ interrupt-names: ++ items: ++ - const: vring ++ + if: + properties: + compatible: +@@ -171,6 +182,9 @@ + <0x22400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am65x-pru0_0-fw"; ++ interrupt-parent = <&icssg0_intc>; ++ interrupts = <16 2 2>; ++ interrupt-names = "vring"; + }; + + rtu0_0: rtu@4000 { +@@ -180,6 +194,9 @@ + <0x23400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am65x-rtu0_0-fw"; ++ interrupt-parent = <&icssg0_intc>; ++ interrupts = <20 4 4>; ++ interrupt-names = "vring"; + }; + + tx_pru0_0: txpru@a000 { +@@ -198,6 +215,9 @@ + <0x24400 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am65x-pru0_1-fw"; ++ interrupt-parent = <&icssg0_intc>; ++ interrupts = <18 3 3>; ++ interrupt-names = "vring"; + }; + + rtu0_1: rtu@6000 { +@@ -207,6 +227,9 @@ + <0x23c00 0x100>; + reg-names = "iram", "control", "debug"; + firmware-name = "am65x-rtu0_1-fw"; ++ interrupt-parent = <&icssg0_intc>; ++ interrupts = <22 5 5>; ++ interrupt-names = "vring"; + }; + + tx_pru0_1: txpru@c000 { +diff -Naur --no-dereference a/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml b/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml +--- a/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml 2024-01-31 19:19:14.000000000 -0500 ++++ b/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml 2024-03-28 11:26:09.893017428 -0400 +@@ -20,7 +20,26 @@ + enum: + - ti,tps6598x + - apple,cd321x ++ - ti,tps25750 ++ + reg: ++ minItems: 1 ++ items: ++ - description: main PD controller address ++ - description: | ++ I2C slave address field in PBMs input data ++ which is used as the device address when writing the ++ patch for TPS25750. ++ The patch address can be any value except 0x00, 0x20, ++ 0x21, 0x22, and 0x23 ++ ++ reg-names: ++ items: ++ - const: main ++ - const: patch-address ++ ++ reset-gpios: ++ description: GPIO used for the HRESET pin. + maxItems: 1 + + wakeup-source: true +@@ -32,14 +51,47 @@ + items: + - const: irq + ++ firmware-name: ++ description: | ++ Should contain the name of the default patch binary ++ file located on the firmware search path which is ++ used to switch the controller into APP mode. ++ This is used when tps25750 doesn't have an EEPROM ++ connected to it. ++ maxItems: 1 ++ + required: + - compatible + - reg + ++allOf: ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: ti,tps25750 ++ then: ++ properties: ++ reg: ++ maxItems: 2 ++ ++ connector: ++ required: ++ - data-role ++ ++ required: ++ - connector ++ - reg-names ++ else: ++ properties: ++ reg: ++ maxItems: 1 ++ + additionalProperties: true + + examples: + - | ++ #include + #include + i2c { + #address-cells = <1>; +@@ -56,6 +108,7 @@ + + pinctrl-names = "default"; + pinctrl-0 = <&typec_pins>; ++ reset-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + + typec_con: connector { + compatible = "usb-c-connector"; +@@ -65,6 +118,38 @@ + remote-endpoint = <&otg_ep>; + }; + }; ++ }; ++ }; ++ }; ++ ++ - | ++ #include ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ typec@21 { ++ compatible = "ti,tps25750"; ++ reg = <0x21>, <0x0f>; ++ reg-names = "main", "patch-address"; ++ ++ interrupt-parent = <&msmgpio>; ++ interrupts = <100 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-names = "irq"; ++ firmware-name = "tps25750.bin"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&typec_pins>; ++ ++ typec_con0: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ data-role = "dual"; ++ port { ++ typec_ep0: endpoint { ++ remote-endpoint = <&otg_ep>; ++ }; ++ }; + }; + }; + }; +diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-am62p.c b/drivers/dma/ti/k3-psil-am62p.c +--- a/drivers/dma/ti/k3-psil-am62p.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/dma/ti/k3-psil-am62p.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,325 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com ++ */ ++ ++#include ++ ++#include "k3-psil-priv.h" ++ ++#define PSIL_PDMA_XY_TR(x) \ ++ { \ ++ .thread_id = x, \ ++ .ep_config = { \ ++ .ep_type = PSIL_EP_PDMA_XY, \ ++ .mapped_channel_id = -1, \ ++ .default_flow_id = -1, \ ++ }, \ ++ } ++ ++#define PSIL_PDMA_XY_PKT(x) \ ++ { \ ++ .thread_id = x, \ ++ .ep_config = { \ ++ .ep_type = PSIL_EP_PDMA_XY, \ ++ .mapped_channel_id = -1, \ ++ .default_flow_id = -1, \ ++ .pkt_mode = 1, \ ++ }, \ ++ } ++ ++#define PSIL_ETHERNET(x, ch, flow_base, flow_cnt) \ ++ { \ ++ .thread_id = x, \ ++ .ep_config = { \ ++ .ep_type = PSIL_EP_NATIVE, \ ++ .pkt_mode = 1, \ ++ .needs_epib = 1, \ ++ .psd_size = 16, \ ++ .mapped_channel_id = ch, \ ++ .flow_start = flow_base, \ ++ .flow_num = flow_cnt, \ ++ .default_flow_id = flow_base, \ ++ }, \ ++ } ++ ++#define PSIL_SAUL(x, ch, flow_base, flow_cnt, default_flow, tx) \ ++ { \ ++ .thread_id = x, \ ++ .ep_config = { \ ++ .ep_type = PSIL_EP_NATIVE, \ ++ .pkt_mode = 1, \ ++ .needs_epib = 1, \ ++ .psd_size = 64, \ ++ .mapped_channel_id = ch, \ ++ .flow_start = flow_base, \ ++ .flow_num = flow_cnt, \ ++ .default_flow_id = default_flow, \ ++ .notdpkt = tx, \ ++ }, \ ++ } ++ ++#define PSIL_PDMA_MCASP(x) \ ++ { \ ++ .thread_id = x, \ ++ .ep_config = { \ ++ .ep_type = PSIL_EP_PDMA_XY, \ ++ .pdma_acc32 = 1, \ ++ .pdma_burst = 1, \ ++ }, \ ++ } ++ ++#define PSIL_CSI2RX(x) \ ++ { \ ++ .thread_id = x, \ ++ .ep_config = { \ ++ .ep_type = PSIL_EP_NATIVE, \ ++ }, \ ++ } ++ ++/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ ++static struct psil_ep am62p_src_ep_map[] = { ++ /* SAUL */ ++ PSIL_SAUL(0x7504, 20, 35, 8, 35, 0), ++ PSIL_SAUL(0x7505, 21, 35, 8, 36, 0), ++ PSIL_SAUL(0x7506, 22, 43, 8, 43, 0), ++ PSIL_SAUL(0x7507, 23, 43, 8, 44, 0), ++ /* PDMA_MAIN0 - SPI0-2 */ ++ PSIL_PDMA_XY_PKT(0x4300), ++ PSIL_PDMA_XY_PKT(0x4301), ++ PSIL_PDMA_XY_PKT(0x4302), ++ PSIL_PDMA_XY_PKT(0x4303), ++ PSIL_PDMA_XY_PKT(0x4304), ++ PSIL_PDMA_XY_PKT(0x4305), ++ PSIL_PDMA_XY_PKT(0x4306), ++ PSIL_PDMA_XY_PKT(0x4307), ++ PSIL_PDMA_XY_PKT(0x4308), ++ PSIL_PDMA_XY_PKT(0x4309), ++ PSIL_PDMA_XY_PKT(0x430a), ++ PSIL_PDMA_XY_PKT(0x430b), ++ /* PDMA_MAIN1 - UART0-6 */ ++ PSIL_PDMA_XY_PKT(0x4400), ++ PSIL_PDMA_XY_PKT(0x4401), ++ PSIL_PDMA_XY_PKT(0x4402), ++ PSIL_PDMA_XY_PKT(0x4403), ++ PSIL_PDMA_XY_PKT(0x4404), ++ PSIL_PDMA_XY_PKT(0x4405), ++ PSIL_PDMA_XY_PKT(0x4406), ++ /* PDMA_MAIN2 - MCASP0-2 */ ++ PSIL_PDMA_MCASP(0x4500), ++ PSIL_PDMA_MCASP(0x4501), ++ PSIL_PDMA_MCASP(0x4502), ++ /* CPSW3G */ ++ PSIL_ETHERNET(0x4600, 19, 19, 16), ++ /* CSI2RX */ ++ PSIL_CSI2RX(0x5000), ++ PSIL_CSI2RX(0x5001), ++ PSIL_CSI2RX(0x5002), ++ PSIL_CSI2RX(0x5003), ++ PSIL_CSI2RX(0x5004), ++ PSIL_CSI2RX(0x5005), ++ PSIL_CSI2RX(0x5006), ++ PSIL_CSI2RX(0x5007), ++ PSIL_CSI2RX(0x5008), ++ PSIL_CSI2RX(0x5009), ++ PSIL_CSI2RX(0x500a), ++ PSIL_CSI2RX(0x500b), ++ PSIL_CSI2RX(0x500c), ++ PSIL_CSI2RX(0x500d), ++ PSIL_CSI2RX(0x500e), ++ PSIL_CSI2RX(0x500f), ++ PSIL_CSI2RX(0x5010), ++ PSIL_CSI2RX(0x5011), ++ PSIL_CSI2RX(0x5012), ++ PSIL_CSI2RX(0x5013), ++ PSIL_CSI2RX(0x5014), ++ PSIL_CSI2RX(0x5015), ++ PSIL_CSI2RX(0x5016), ++ PSIL_CSI2RX(0x5017), ++ PSIL_CSI2RX(0x5018), ++ PSIL_CSI2RX(0x5019), ++ PSIL_CSI2RX(0x501a), ++ PSIL_CSI2RX(0x501b), ++ PSIL_CSI2RX(0x501c), ++ PSIL_CSI2RX(0x501d), ++ PSIL_CSI2RX(0x501e), ++ PSIL_CSI2RX(0x501f), ++ PSIL_CSI2RX(0x5000), ++ PSIL_CSI2RX(0x5001), ++ PSIL_CSI2RX(0x5002), ++ PSIL_CSI2RX(0x5003), ++ PSIL_CSI2RX(0x5004), ++ PSIL_CSI2RX(0x5005), ++ PSIL_CSI2RX(0x5006), ++ PSIL_CSI2RX(0x5007), ++ PSIL_CSI2RX(0x5008), ++ PSIL_CSI2RX(0x5009), ++ PSIL_CSI2RX(0x500a), ++ PSIL_CSI2RX(0x500b), ++ PSIL_CSI2RX(0x500c), ++ PSIL_CSI2RX(0x500d), ++ PSIL_CSI2RX(0x500e), ++ PSIL_CSI2RX(0x500f), ++ PSIL_CSI2RX(0x5010), ++ PSIL_CSI2RX(0x5011), ++ PSIL_CSI2RX(0x5012), ++ PSIL_CSI2RX(0x5013), ++ PSIL_CSI2RX(0x5014), ++ PSIL_CSI2RX(0x5015), ++ PSIL_CSI2RX(0x5016), ++ PSIL_CSI2RX(0x5017), ++ PSIL_CSI2RX(0x5018), ++ PSIL_CSI2RX(0x5019), ++ PSIL_CSI2RX(0x501a), ++ PSIL_CSI2RX(0x501b), ++ PSIL_CSI2RX(0x501c), ++ PSIL_CSI2RX(0x501d), ++ PSIL_CSI2RX(0x501e), ++ PSIL_CSI2RX(0x501f), ++ /* CSIRX 1-3 (only for J722S) */ ++ PSIL_CSI2RX(0x5100), ++ PSIL_CSI2RX(0x5101), ++ PSIL_CSI2RX(0x5102), ++ PSIL_CSI2RX(0x5103), ++ PSIL_CSI2RX(0x5104), ++ PSIL_CSI2RX(0x5105), ++ PSIL_CSI2RX(0x5106), ++ PSIL_CSI2RX(0x5107), ++ PSIL_CSI2RX(0x5108), ++ PSIL_CSI2RX(0x5109), ++ PSIL_CSI2RX(0x510a), ++ PSIL_CSI2RX(0x510b), ++ PSIL_CSI2RX(0x510c), ++ PSIL_CSI2RX(0x510d), ++ PSIL_CSI2RX(0x510e), ++ PSIL_CSI2RX(0x510f), ++ PSIL_CSI2RX(0x5110), ++ PSIL_CSI2RX(0x5111), ++ PSIL_CSI2RX(0x5112), ++ PSIL_CSI2RX(0x5113), ++ PSIL_CSI2RX(0x5114), ++ PSIL_CSI2RX(0x5115), ++ PSIL_CSI2RX(0x5116), ++ PSIL_CSI2RX(0x5117), ++ PSIL_CSI2RX(0x5118), ++ PSIL_CSI2RX(0x5119), ++ PSIL_CSI2RX(0x511a), ++ PSIL_CSI2RX(0x511b), ++ PSIL_CSI2RX(0x511c), ++ PSIL_CSI2RX(0x511d), ++ PSIL_CSI2RX(0x511e), ++ PSIL_CSI2RX(0x511f), ++ PSIL_CSI2RX(0x5200), ++ PSIL_CSI2RX(0x5201), ++ PSIL_CSI2RX(0x5202), ++ PSIL_CSI2RX(0x5203), ++ PSIL_CSI2RX(0x5204), ++ PSIL_CSI2RX(0x5205), ++ PSIL_CSI2RX(0x5206), ++ PSIL_CSI2RX(0x5207), ++ PSIL_CSI2RX(0x5208), ++ PSIL_CSI2RX(0x5209), ++ PSIL_CSI2RX(0x520a), ++ PSIL_CSI2RX(0x520b), ++ PSIL_CSI2RX(0x520c), ++ PSIL_CSI2RX(0x520d), ++ PSIL_CSI2RX(0x520e), ++ PSIL_CSI2RX(0x520f), ++ PSIL_CSI2RX(0x5210), ++ PSIL_CSI2RX(0x5211), ++ PSIL_CSI2RX(0x5212), ++ PSIL_CSI2RX(0x5213), ++ PSIL_CSI2RX(0x5214), ++ PSIL_CSI2RX(0x5215), ++ PSIL_CSI2RX(0x5216), ++ PSIL_CSI2RX(0x5217), ++ PSIL_CSI2RX(0x5218), ++ PSIL_CSI2RX(0x5219), ++ PSIL_CSI2RX(0x521a), ++ PSIL_CSI2RX(0x521b), ++ PSIL_CSI2RX(0x521c), ++ PSIL_CSI2RX(0x521d), ++ PSIL_CSI2RX(0x521e), ++ PSIL_CSI2RX(0x521f), ++ PSIL_CSI2RX(0x5300), ++ PSIL_CSI2RX(0x5301), ++ PSIL_CSI2RX(0x5302), ++ PSIL_CSI2RX(0x5303), ++ PSIL_CSI2RX(0x5304), ++ PSIL_CSI2RX(0x5305), ++ PSIL_CSI2RX(0x5306), ++ PSIL_CSI2RX(0x5307), ++ PSIL_CSI2RX(0x5308), ++ PSIL_CSI2RX(0x5309), ++ PSIL_CSI2RX(0x530a), ++ PSIL_CSI2RX(0x530b), ++ PSIL_CSI2RX(0x530c), ++ PSIL_CSI2RX(0x530d), ++ PSIL_CSI2RX(0x530e), ++ PSIL_CSI2RX(0x530f), ++ PSIL_CSI2RX(0x5310), ++ PSIL_CSI2RX(0x5311), ++ PSIL_CSI2RX(0x5312), ++ PSIL_CSI2RX(0x5313), ++ PSIL_CSI2RX(0x5314), ++ PSIL_CSI2RX(0x5315), ++ PSIL_CSI2RX(0x5316), ++ PSIL_CSI2RX(0x5317), ++ PSIL_CSI2RX(0x5318), ++ PSIL_CSI2RX(0x5319), ++ PSIL_CSI2RX(0x531a), ++ PSIL_CSI2RX(0x531b), ++ PSIL_CSI2RX(0x531c), ++ PSIL_CSI2RX(0x531d), ++ PSIL_CSI2RX(0x531e), ++ PSIL_CSI2RX(0x531f), ++}; ++ ++/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ ++static struct psil_ep am62p_dst_ep_map[] = { ++ /* SAUL */ ++ PSIL_SAUL(0xf500, 27, 83, 8, 83, 1), ++ PSIL_SAUL(0xf501, 28, 91, 8, 91, 1), ++ /* PDMA_MAIN0 - SPI0-2 */ ++ PSIL_PDMA_XY_PKT(0xc300), ++ PSIL_PDMA_XY_PKT(0xc301), ++ PSIL_PDMA_XY_PKT(0xc302), ++ PSIL_PDMA_XY_PKT(0xc303), ++ PSIL_PDMA_XY_PKT(0xc304), ++ PSIL_PDMA_XY_PKT(0xc305), ++ PSIL_PDMA_XY_PKT(0xc306), ++ PSIL_PDMA_XY_PKT(0xc307), ++ PSIL_PDMA_XY_PKT(0xc308), ++ PSIL_PDMA_XY_PKT(0xc309), ++ PSIL_PDMA_XY_PKT(0xc30a), ++ PSIL_PDMA_XY_PKT(0xc30b), ++ /* PDMA_MAIN1 - UART0-6 */ ++ PSIL_PDMA_XY_PKT(0xc400), ++ PSIL_PDMA_XY_PKT(0xc401), ++ PSIL_PDMA_XY_PKT(0xc402), ++ PSIL_PDMA_XY_PKT(0xc403), ++ PSIL_PDMA_XY_PKT(0xc404), ++ PSIL_PDMA_XY_PKT(0xc405), ++ PSIL_PDMA_XY_PKT(0xc406), ++ /* PDMA_MAIN2 - MCASP0-2 */ ++ PSIL_PDMA_MCASP(0xc500), ++ PSIL_PDMA_MCASP(0xc501), ++ PSIL_PDMA_MCASP(0xc502), ++ /* CPSW3G */ ++ PSIL_ETHERNET(0xc600, 19, 19, 8), ++ PSIL_ETHERNET(0xc601, 20, 27, 8), ++ PSIL_ETHERNET(0xc602, 21, 35, 8), ++ PSIL_ETHERNET(0xc603, 22, 43, 8), ++ PSIL_ETHERNET(0xc604, 23, 51, 8), ++ PSIL_ETHERNET(0xc605, 24, 59, 8), ++ PSIL_ETHERNET(0xc606, 25, 67, 8), ++ PSIL_ETHERNET(0xc607, 26, 75, 8), ++}; ++ ++struct psil_ep_map am62p_ep_map = { ++ .name = "am62p", ++ .src = am62p_src_ep_map, ++ .src_count = ARRAY_SIZE(am62p_src_ep_map), ++ .dst = am62p_dst_ep_map, ++ .dst_count = ARRAY_SIZE(am62p_dst_ep_map), ++}; +diff -Naur --no-dereference a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c +--- a/drivers/dma/ti/k3-psil.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/dma/ti/k3-psil.c 2024-03-28 11:26:09.897017444 -0400 +@@ -26,6 +26,8 @@ + { .family = "AM62X", .data = &am62_ep_map }, + { .family = "AM62AX", .data = &am62a_ep_map }, + { .family = "J784S4", .data = &j784s4_ep_map }, ++ { .family = "AM62PX", .data = &am62p_ep_map }, ++ { .family = "J722S", .data = &am62p_ep_map }, + { /* sentinel */ } + }; + +diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-j721s2.c b/drivers/dma/ti/k3-psil-j721s2.c +--- a/drivers/dma/ti/k3-psil-j721s2.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/dma/ti/k3-psil-j721s2.c 2024-03-28 11:26:09.897017444 -0400 +@@ -57,6 +57,14 @@ + }, \ + } + ++#define PSIL_CSI2RX(x) \ ++ { \ ++ .thread_id = x, \ ++ .ep_config = { \ ++ .ep_type = PSIL_EP_NATIVE, \ ++ }, \ ++ } ++ + /* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ + static struct psil_ep j721s2_src_ep_map[] = { + /* PDMA_MCASP - McASP0-4 */ +@@ -114,6 +122,71 @@ + PSIL_PDMA_XY_PKT(0x4707), + PSIL_PDMA_XY_PKT(0x4708), + PSIL_PDMA_XY_PKT(0x4709), ++ /* CSI2RX */ ++ PSIL_CSI2RX(0x4940), ++ PSIL_CSI2RX(0x4941), ++ PSIL_CSI2RX(0x4942), ++ PSIL_CSI2RX(0x4943), ++ PSIL_CSI2RX(0x4944), ++ PSIL_CSI2RX(0x4945), ++ PSIL_CSI2RX(0x4946), ++ PSIL_CSI2RX(0x4947), ++ PSIL_CSI2RX(0x4948), ++ PSIL_CSI2RX(0x4949), ++ PSIL_CSI2RX(0x494a), ++ PSIL_CSI2RX(0x494b), ++ PSIL_CSI2RX(0x494c), ++ PSIL_CSI2RX(0x494d), ++ PSIL_CSI2RX(0x494e), ++ PSIL_CSI2RX(0x494f), ++ PSIL_CSI2RX(0x4950), ++ PSIL_CSI2RX(0x4951), ++ PSIL_CSI2RX(0x4952), ++ PSIL_CSI2RX(0x4953), ++ PSIL_CSI2RX(0x4954), ++ PSIL_CSI2RX(0x4955), ++ PSIL_CSI2RX(0x4956), ++ PSIL_CSI2RX(0x4957), ++ PSIL_CSI2RX(0x4958), ++ PSIL_CSI2RX(0x4959), ++ PSIL_CSI2RX(0x495a), ++ PSIL_CSI2RX(0x495b), ++ PSIL_CSI2RX(0x495c), ++ PSIL_CSI2RX(0x495d), ++ PSIL_CSI2RX(0x495e), ++ PSIL_CSI2RX(0x495f), ++ PSIL_CSI2RX(0x4960), ++ PSIL_CSI2RX(0x4961), ++ PSIL_CSI2RX(0x4962), ++ PSIL_CSI2RX(0x4963), ++ PSIL_CSI2RX(0x4964), ++ PSIL_CSI2RX(0x4965), ++ PSIL_CSI2RX(0x4966), ++ PSIL_CSI2RX(0x4967), ++ PSIL_CSI2RX(0x4968), ++ PSIL_CSI2RX(0x4969), ++ PSIL_CSI2RX(0x496a), ++ PSIL_CSI2RX(0x496b), ++ PSIL_CSI2RX(0x496c), ++ PSIL_CSI2RX(0x496d), ++ PSIL_CSI2RX(0x496e), ++ PSIL_CSI2RX(0x496f), ++ PSIL_CSI2RX(0x4970), ++ PSIL_CSI2RX(0x4971), ++ PSIL_CSI2RX(0x4972), ++ PSIL_CSI2RX(0x4973), ++ PSIL_CSI2RX(0x4974), ++ PSIL_CSI2RX(0x4975), ++ PSIL_CSI2RX(0x4976), ++ PSIL_CSI2RX(0x4977), ++ PSIL_CSI2RX(0x4978), ++ PSIL_CSI2RX(0x4979), ++ PSIL_CSI2RX(0x497a), ++ PSIL_CSI2RX(0x497b), ++ PSIL_CSI2RX(0x497c), ++ PSIL_CSI2RX(0x497d), ++ PSIL_CSI2RX(0x497e), ++ PSIL_CSI2RX(0x497f), + /* MAIN SA2UL */ + PSIL_SA2UL(0x4a40, 0), + PSIL_SA2UL(0x4a41, 0), +diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h +--- a/drivers/dma/ti/k3-psil-priv.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/dma/ti/k3-psil-priv.h 2024-03-28 11:26:09.897017444 -0400 +@@ -45,5 +45,6 @@ + extern struct psil_ep_map am62_ep_map; + extern struct psil_ep_map am62a_ep_map; + extern struct psil_ep_map j784s4_ep_map; ++extern struct psil_ep_map am62p_ep_map; + + #endif /* K3_PSIL_PRIV_H_ */ +diff -Naur --no-dereference a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c +--- a/drivers/dma/ti/k3-udma.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/dma/ti/k3-udma.c 2024-03-28 11:26:09.897017444 -0400 +@@ -3968,6 +3968,7 @@ + { + struct udma_chan *uc = to_udma_chan(&vc->chan); + struct udma_desc *d; ++ u8 status; + + if (!vd) + return; +@@ -3977,12 +3978,12 @@ + if (d->metadata_size) + udma_fetch_epib(uc, d); + +- /* Provide residue information for the client */ + if (result) { + void *desc_vaddr = udma_curr_cppi5_desc_vaddr(d, d->desc_idx); + + if (cppi5_desc_get_type(desc_vaddr) == + CPPI5_INFO0_DESC_TYPE_VAL_HOST) { ++ /* Provide residue information for the client */ + result->residue = d->residue - + cppi5_hdesc_get_pktlen(desc_vaddr); + if (result->residue) +@@ -3991,7 +3992,12 @@ + result->result = DMA_TRANS_NOERROR; + } else { + result->residue = 0; +- result->result = DMA_TRANS_NOERROR; ++ /* Propagate TR Response errors to the client */ ++ status = d->hwdesc[0].tr_resp_base->status; ++ if (status) ++ result->result = DMA_TRANS_ABORTED; ++ else ++ result->result = DMA_TRANS_NOERROR; + } + } + } +@@ -4441,6 +4447,8 @@ + { .family = "AM62X", .data = &am64_soc_data }, + { .family = "AM62AX", .data = &am64_soc_data }, + { .family = "J784S4", .data = &j721e_soc_data }, ++ { .family = "AM62PX", .data = &am64_soc_data }, ++ { .family = "J722S", .data = &am64_soc_data }, + { /* sentinel */ } + }; + +diff -Naur --no-dereference a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c +--- a/drivers/dma/ti/k3-udma-glue.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/dma/ti/k3-udma-glue.c 2024-03-28 11:26:09.897017444 -0400 +@@ -111,6 +111,35 @@ + return 0; + } + ++static int of_k3_udma_glue_parse_chn_common(struct k3_udma_glue_common *common, u32 thread_id, ++ bool tx_chn) ++{ ++ if (tx_chn && !(thread_id & K3_PSIL_DST_THREAD_ID_OFFSET)) ++ return -EINVAL; ++ ++ if (!tx_chn && (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET)) ++ return -EINVAL; ++ ++ /* get psil endpoint config */ ++ common->ep_config = psil_get_ep_config(thread_id); ++ if (IS_ERR(common->ep_config)) { ++ dev_err(common->dev, ++ "No configuration for psi-l thread 0x%04x\n", ++ thread_id); ++ return PTR_ERR(common->ep_config); ++ } ++ ++ common->epib = common->ep_config->needs_epib; ++ common->psdata_size = common->ep_config->psd_size; ++ ++ if (tx_chn) ++ common->dst_thread = thread_id; ++ else ++ common->src_thread = thread_id; ++ ++ return 0; ++} ++ + static int of_k3_udma_glue_parse_chn(struct device_node *chn_np, + const char *name, struct k3_udma_glue_common *common, + bool tx_chn) +@@ -153,38 +182,32 @@ + common->atype_asel = dma_spec.args[1]; + } + +- if (tx_chn && !(thread_id & K3_PSIL_DST_THREAD_ID_OFFSET)) { +- ret = -EINVAL; +- goto out_put_spec; +- } ++ ret = of_k3_udma_glue_parse_chn_common(common, thread_id, tx_chn); + +- if (!tx_chn && (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET)) { +- ret = -EINVAL; +- goto out_put_spec; +- } ++out_put_spec: ++ of_node_put(dma_spec.np); ++ return ret; ++} + +- /* get psil endpoint config */ +- common->ep_config = psil_get_ep_config(thread_id); +- if (IS_ERR(common->ep_config)) { +- dev_err(common->dev, +- "No configuration for psi-l thread 0x%04x\n", +- thread_id); +- ret = PTR_ERR(common->ep_config); +- goto out_put_spec; +- } ++static int ++of_k3_udma_glue_parse_chn_by_id(struct device_node *udmax_np, struct k3_udma_glue_common *common, ++ bool tx_chn, u32 thread_id) ++{ ++ int ret = 0; + +- common->epib = common->ep_config->needs_epib; +- common->psdata_size = common->ep_config->psd_size; ++ if (unlikely(!udmax_np)) ++ return -EINVAL; + +- if (tx_chn) +- common->dst_thread = thread_id; +- else +- common->src_thread = thread_id; ++ ret = of_k3_udma_glue_parse(udmax_np, common); ++ if (ret) ++ goto out_put_spec; ++ ++ ret = of_k3_udma_glue_parse_chn_common(common, thread_id, tx_chn); + + out_put_spec: +- of_node_put(dma_spec.np); ++ of_node_put(udmax_np); + return ret; +-}; ++} + + static void k3_udma_glue_dump_tx_chn(struct k3_udma_glue_tx_channel *tx_chn) + { +@@ -251,29 +274,13 @@ + return tisci_rm->tisci_udmap_ops->tx_ch_cfg(tisci_rm->tisci, &req); + } + +-struct k3_udma_glue_tx_channel *k3_udma_glue_request_tx_chn(struct device *dev, +- const char *name, struct k3_udma_glue_tx_channel_cfg *cfg) ++static int ++k3_udma_glue_request_tx_chn_common(struct device *dev, ++ struct k3_udma_glue_tx_channel *tx_chn, ++ struct k3_udma_glue_tx_channel_cfg *cfg) + { +- struct k3_udma_glue_tx_channel *tx_chn; + int ret; + +- tx_chn = devm_kzalloc(dev, sizeof(*tx_chn), GFP_KERNEL); +- if (!tx_chn) +- return ERR_PTR(-ENOMEM); +- +- tx_chn->common.dev = dev; +- tx_chn->common.swdata_size = cfg->swdata_size; +- tx_chn->tx_pause_on_err = cfg->tx_pause_on_err; +- tx_chn->tx_filt_einfo = cfg->tx_filt_einfo; +- tx_chn->tx_filt_pswords = cfg->tx_filt_pswords; +- tx_chn->tx_supr_tdpkt = cfg->tx_supr_tdpkt; +- +- /* parse of udmap channel */ +- ret = of_k3_udma_glue_parse_chn(dev->of_node, name, +- &tx_chn->common, true); +- if (ret) +- goto err; +- + tx_chn->common.hdesc_size = cppi5_hdesc_calc_size(tx_chn->common.epib, + tx_chn->common.psdata_size, + tx_chn->common.swdata_size); +@@ -289,7 +296,7 @@ + if (IS_ERR(tx_chn->udma_tchanx)) { + ret = PTR_ERR(tx_chn->udma_tchanx); + dev_err(dev, "UDMAX tchanx get err %d\n", ret); +- goto err; ++ return ret; + } + tx_chn->udma_tchan_id = xudma_tchan_get_id(tx_chn->udma_tchanx); + +@@ -302,7 +309,7 @@ + dev_err(dev, "Channel Device registration failed %d\n", ret); + put_device(&tx_chn->common.chan_dev); + tx_chn->common.chan_dev.parent = NULL; +- goto err; ++ return ret; + } + + if (xudma_is_pktdma(tx_chn->common.udmax)) { +@@ -326,7 +333,7 @@ + &tx_chn->ringtxcq); + if (ret) { + dev_err(dev, "Failed to get TX/TXCQ rings %d\n", ret); +- goto err; ++ return ret; + } + + /* Set the dma_dev for the rings to be configured */ +@@ -342,13 +349,13 @@ + ret = k3_ringacc_ring_cfg(tx_chn->ringtx, &cfg->tx_cfg); + if (ret) { + dev_err(dev, "Failed to cfg ringtx %d\n", ret); +- goto err; ++ return ret; + } + + ret = k3_ringacc_ring_cfg(tx_chn->ringtxcq, &cfg->txcq_cfg); + if (ret) { + dev_err(dev, "Failed to cfg ringtx %d\n", ret); +- goto err; ++ return ret; + } + + /* request and cfg psi-l */ +@@ -359,11 +366,42 @@ + ret = k3_udma_glue_cfg_tx_chn(tx_chn); + if (ret) { + dev_err(dev, "Failed to cfg tchan %d\n", ret); +- goto err; ++ return ret; + } + + k3_udma_glue_dump_tx_chn(tx_chn); + ++ return 0; ++} ++ ++struct k3_udma_glue_tx_channel * ++k3_udma_glue_request_tx_chn(struct device *dev, const char *name, ++ struct k3_udma_glue_tx_channel_cfg *cfg) ++{ ++ struct k3_udma_glue_tx_channel *tx_chn; ++ int ret; ++ ++ tx_chn = devm_kzalloc(dev, sizeof(*tx_chn), GFP_KERNEL); ++ if (!tx_chn) ++ return ERR_PTR(-ENOMEM); ++ ++ tx_chn->common.dev = dev; ++ tx_chn->common.swdata_size = cfg->swdata_size; ++ tx_chn->tx_pause_on_err = cfg->tx_pause_on_err; ++ tx_chn->tx_filt_einfo = cfg->tx_filt_einfo; ++ tx_chn->tx_filt_pswords = cfg->tx_filt_pswords; ++ tx_chn->tx_supr_tdpkt = cfg->tx_supr_tdpkt; ++ ++ /* parse of udmap channel */ ++ ret = of_k3_udma_glue_parse_chn(dev->of_node, name, ++ &tx_chn->common, true); ++ if (ret) ++ goto err; ++ ++ ret = k3_udma_glue_request_tx_chn_common(dev, tx_chn, cfg); ++ if (ret) ++ goto err; ++ + return tx_chn; + + err: +@@ -372,6 +410,41 @@ + } + EXPORT_SYMBOL_GPL(k3_udma_glue_request_tx_chn); + ++struct k3_udma_glue_tx_channel * ++k3_udma_glue_request_tx_chn_for_thread_id(struct device *dev, ++ struct k3_udma_glue_tx_channel_cfg *cfg, ++ struct device_node *udmax_np, u32 thread_id) ++{ ++ struct k3_udma_glue_tx_channel *tx_chn; ++ int ret; ++ ++ tx_chn = devm_kzalloc(dev, sizeof(*tx_chn), GFP_KERNEL); ++ if (!tx_chn) ++ return ERR_PTR(-ENOMEM); ++ ++ tx_chn->common.dev = dev; ++ tx_chn->common.swdata_size = cfg->swdata_size; ++ tx_chn->tx_pause_on_err = cfg->tx_pause_on_err; ++ tx_chn->tx_filt_einfo = cfg->tx_filt_einfo; ++ tx_chn->tx_filt_pswords = cfg->tx_filt_pswords; ++ tx_chn->tx_supr_tdpkt = cfg->tx_supr_tdpkt; ++ ++ ret = of_k3_udma_glue_parse_chn_by_id(udmax_np, &tx_chn->common, true, thread_id); ++ if (ret) ++ goto err; ++ ++ ret = k3_udma_glue_request_tx_chn_common(dev, tx_chn, cfg); ++ if (ret) ++ goto err; ++ ++ return tx_chn; ++ ++err: ++ k3_udma_glue_release_tx_chn(tx_chn); ++ return ERR_PTR(ret); ++} ++EXPORT_SYMBOL_GPL(k3_udma_glue_request_tx_chn_for_thread_id); ++ + void k3_udma_glue_release_tx_chn(struct k3_udma_glue_tx_channel *tx_chn) + { + if (tx_chn->psil_paired) { +@@ -1000,12 +1073,59 @@ + return ERR_PTR(ret); + } + ++static int ++k3_udma_glue_request_remote_rx_chn_common(struct k3_udma_glue_rx_channel *rx_chn, ++ struct k3_udma_glue_rx_channel_cfg *cfg, ++ struct device *dev) ++{ ++ int ret, i; ++ ++ rx_chn->common.hdesc_size = cppi5_hdesc_calc_size(rx_chn->common.epib, ++ rx_chn->common.psdata_size, ++ rx_chn->common.swdata_size); ++ ++ rx_chn->flows = devm_kcalloc(dev, rx_chn->flow_num, ++ sizeof(*rx_chn->flows), GFP_KERNEL); ++ if (!rx_chn->flows) ++ return -ENOMEM; ++ ++ rx_chn->common.chan_dev.class = &k3_udma_glue_devclass; ++ rx_chn->common.chan_dev.parent = xudma_get_device(rx_chn->common.udmax); ++ dev_set_name(&rx_chn->common.chan_dev, "rchan_remote-0x%04x-0x%02x", ++ rx_chn->common.src_thread, rx_chn->flow_id_base); ++ ret = device_register(&rx_chn->common.chan_dev); ++ if (ret) { ++ dev_err(dev, "Channel Device registration failed %d\n", ret); ++ put_device(&rx_chn->common.chan_dev); ++ rx_chn->common.chan_dev.parent = NULL; ++ return ret; ++ } ++ ++ if (xudma_is_pktdma(rx_chn->common.udmax)) { ++ /* prepare the channel device as coherent */ ++ rx_chn->common.chan_dev.dma_coherent = true; ++ dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev, ++ DMA_BIT_MASK(48)); ++ } ++ ++ ret = k3_udma_glue_allocate_rx_flows(rx_chn, cfg); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < rx_chn->flow_num; i++) ++ rx_chn->flows[i].udma_rflow_id = rx_chn->flow_id_base + i; ++ ++ k3_udma_glue_dump_rx_chn(rx_chn); ++ ++ return 0; ++} ++ + static struct k3_udma_glue_rx_channel * + k3_udma_glue_request_remote_rx_chn(struct device *dev, const char *name, + struct k3_udma_glue_rx_channel_cfg *cfg) + { + struct k3_udma_glue_rx_channel *rx_chn; +- int ret, i; ++ int ret; + + if (cfg->flow_id_num <= 0 || + cfg->flow_id_use_rxchan_id || +@@ -1036,44 +1156,55 @@ + if (ret) + goto err; + +- rx_chn->common.hdesc_size = cppi5_hdesc_calc_size(rx_chn->common.epib, +- rx_chn->common.psdata_size, +- rx_chn->common.swdata_size); +- +- rx_chn->flows = devm_kcalloc(dev, rx_chn->flow_num, +- sizeof(*rx_chn->flows), GFP_KERNEL); +- if (!rx_chn->flows) { +- ret = -ENOMEM; ++ ret = k3_udma_glue_request_remote_rx_chn_common(rx_chn, cfg, dev); ++ if (ret) + goto err; +- } + +- rx_chn->common.chan_dev.class = &k3_udma_glue_devclass; +- rx_chn->common.chan_dev.parent = xudma_get_device(rx_chn->common.udmax); +- dev_set_name(&rx_chn->common.chan_dev, "rchan_remote-0x%04x", +- rx_chn->common.src_thread); +- ret = device_register(&rx_chn->common.chan_dev); +- if (ret) { +- dev_err(dev, "Channel Device registration failed %d\n", ret); +- put_device(&rx_chn->common.chan_dev); +- rx_chn->common.chan_dev.parent = NULL; +- goto err; +- } ++ return rx_chn; + +- if (xudma_is_pktdma(rx_chn->common.udmax)) { +- /* prepare the channel device as coherent */ +- rx_chn->common.chan_dev.dma_coherent = true; +- dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev, +- DMA_BIT_MASK(48)); +- } ++err: ++ k3_udma_glue_release_rx_chn(rx_chn); ++ return ERR_PTR(ret); ++} + +- ret = k3_udma_glue_allocate_rx_flows(rx_chn, cfg); ++struct k3_udma_glue_rx_channel * ++k3_udma_glue_request_remote_rx_chn_for_thread_id(struct device *dev, ++ struct k3_udma_glue_rx_channel_cfg *cfg, ++ struct device_node *udmax_np, u32 thread_id) ++{ ++ struct k3_udma_glue_rx_channel *rx_chn; ++ int ret; ++ ++ if (cfg->flow_id_num <= 0 || ++ cfg->flow_id_use_rxchan_id || ++ cfg->def_flow_cfg || ++ cfg->flow_id_base < 0) ++ return ERR_PTR(-EINVAL); ++ ++ /* ++ * Remote RX channel is under control of Remote CPU core, so ++ * Linux can only request and manipulate by dedicated RX flows ++ */ ++ ++ rx_chn = devm_kzalloc(dev, sizeof(*rx_chn), GFP_KERNEL); ++ if (!rx_chn) ++ return ERR_PTR(-ENOMEM); ++ ++ rx_chn->common.dev = dev; ++ rx_chn->common.swdata_size = cfg->swdata_size; ++ rx_chn->remote = true; ++ rx_chn->udma_rchan_id = -1; ++ rx_chn->flow_num = cfg->flow_id_num; ++ rx_chn->flow_id_base = cfg->flow_id_base; ++ rx_chn->psil_paired = false; ++ ++ ret = of_k3_udma_glue_parse_chn_by_id(udmax_np, &rx_chn->common, false, thread_id); + if (ret) + goto err; + +- for (i = 0; i < rx_chn->flow_num; i++) +- rx_chn->flows[i].udma_rflow_id = rx_chn->flow_id_base + i; +- +- k3_udma_glue_dump_rx_chn(rx_chn); ++ ret = k3_udma_glue_request_remote_rx_chn_common(rx_chn, cfg, dev); ++ if (ret) ++ goto err; + + return rx_chn; + +@@ -1081,6 +1212,7 @@ + k3_udma_glue_release_rx_chn(rx_chn); + return ERR_PTR(ret); + } ++EXPORT_SYMBOL_GPL(k3_udma_glue_request_remote_rx_chn_for_thread_id); + + struct k3_udma_glue_rx_channel * + k3_udma_glue_request_rx_chn(struct device *dev, const char *name, +diff -Naur --no-dereference a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile +--- a/drivers/dma/ti/Makefile 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/dma/ti/Makefile 2024-03-28 11:26:09.897017444 -0400 +@@ -12,6 +12,7 @@ + k3-psil-j721s2.o \ + k3-psil-am62.o \ + k3-psil-am62a.o \ +- k3-psil-j784s4.o ++ k3-psil-j784s4.o \ ++ k3-psil-am62p.o + obj-$(CONFIG_TI_K3_PSIL) += k3-psil-lib.o + obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o +diff -Naur --no-dereference a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c +--- a/drivers/firmware/ti_sci.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/firmware/ti_sci.c 2024-03-28 11:26:09.897017444 -0400 +@@ -16,7 +16,10 @@ + #include + #include + #include +-#include ++#include ++#include ++#include ++#include + #include + #include + #include +@@ -472,7 +475,7 @@ + ver->abi_major = rev_info->abi_major; + ver->abi_minor = rev_info->abi_minor; + ver->firmware_revision = rev_info->firmware_revision; +- strncpy(ver->firmware_description, rev_info->firmware_description, ++ strscpy(ver->firmware_description, rev_info->firmware_description, + sizeof(ver->firmware_description)); + + fail: +@@ -2873,7 +2876,6 @@ + const struct ti_sci_handle *ti_sci_get_handle(struct device *dev) + { + struct device_node *ti_sci_np; +- struct list_head *p; + struct ti_sci_handle *handle = NULL; + struct ti_sci_info *info; + +@@ -2888,8 +2890,7 @@ + } + + mutex_lock(&ti_sci_list_mutex); +- list_for_each(p, &ti_sci_list) { +- info = list_entry(p, struct ti_sci_info, node); ++ list_for_each_entry(info, &ti_sci_list, node) { + if (ti_sci_np == info->dev->of_node) { + handle = &info->handle; + info->users++; +@@ -2999,7 +3000,6 @@ + struct ti_sci_handle *handle = NULL; + struct device_node *ti_sci_np; + struct ti_sci_info *info; +- struct list_head *p; + + if (!np) { + pr_err("I need a device pointer\n"); +@@ -3011,8 +3011,7 @@ + return ERR_PTR(-ENODEV); + + mutex_lock(&ti_sci_list_mutex); +- list_for_each(p, &ti_sci_list) { +- info = list_entry(p, struct ti_sci_info, node); ++ list_for_each_entry(info, &ti_sci_list, node) { + if (ti_sci_np == info->dev->of_node) { + handle = &info->handle; + info->users++; +@@ -3297,7 +3296,6 @@ + static int ti_sci_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +- const struct of_device_id *of_id; + const struct ti_sci_desc *desc; + struct ti_sci_xfer *xfer; + struct ti_sci_info *info = NULL; +@@ -3308,12 +3306,7 @@ + int reboot = 0; + u32 h_id; + +- of_id = of_match_device(ti_sci_of_match, dev); +- if (!of_id) { +- dev_err(dev, "OF data missing\n"); +- return -EINVAL; +- } +- desc = of_id->data; ++ desc = device_get_match_data(dev); + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) +diff -Naur --no-dereference a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c +--- a/drivers/gpu/drm/bridge/ite-it66121.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/gpu/drm/bridge/ite-it66121.c 2024-03-28 11:26:09.897017444 -0400 +@@ -1505,7 +1505,6 @@ + + static int it66121_probe(struct i2c_client *client) + { +- const struct i2c_device_id *id = i2c_client_get_device_id(client); + u32 revision_id, vendor_ids[2] = { 0 }, device_ids[2] = { 0 }; + struct device_node *ep; + int ret; +@@ -1527,7 +1526,7 @@ + + ctx->dev = dev; + ctx->client = client; +- ctx->info = (const struct it66121_chip_info *) id->driver_data; ++ ctx->info = i2c_get_match_data(client); + + of_property_read_u32(ep, "bus-width", &ctx->bus_width); + of_node_put(ep); +@@ -1613,13 +1612,6 @@ + mutex_destroy(&ctx->lock); + } + +-static const struct of_device_id it66121_dt_match[] = { +- { .compatible = "ite,it66121" }, +- { .compatible = "ite,it6610" }, +- { } +-}; +-MODULE_DEVICE_TABLE(of, it66121_dt_match); +- + static const struct it66121_chip_info it66121_chip_info = { + .id = ID_IT66121, + .vid = 0x4954, +@@ -1632,6 +1624,13 @@ + .pid = 0x0611, + }; + ++static const struct of_device_id it66121_dt_match[] = { ++ { .compatible = "ite,it66121", &it66121_chip_info }, ++ { .compatible = "ite,it6610", &it6610_chip_info }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, it66121_dt_match); ++ + static const struct i2c_device_id it66121_id[] = { + { "it66121", (kernel_ulong_t) &it66121_chip_info }, + { "it6610", (kernel_ulong_t) &it6610_chip_info }, +diff -Naur --no-dereference a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c +--- a/drivers/gpu/drm/omapdrm/omap_gem.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/gpu/drm/omapdrm/omap_gem.c 2024-03-28 11:26:09.897017444 -0400 +@@ -48,7 +48,7 @@ + * OMAP_BO_MEM_DMA_API flag set) + * + * - buffers imported from dmabuf (with the OMAP_BO_MEM_DMABUF flag set) +- * if they are physically contiguous (when sgt->orig_nents == 1) ++ * if they are physically contiguous + * + * - buffers mapped through the TILER when pin_cnt is not zero, in which + * case the DMA address points to the TILER aperture +@@ -148,12 +148,18 @@ + return drm_vma_node_offset_addr(&obj->vma_node); + } + ++static bool omap_gem_sgt_is_contiguous(struct sg_table *sgt, size_t size) ++{ ++ return !(drm_prime_get_contiguous_size(sgt) < size); ++} ++ + static bool omap_gem_is_contiguous(struct omap_gem_object *omap_obj) + { + if (omap_obj->flags & OMAP_BO_MEM_DMA_API) + return true; + +- if ((omap_obj->flags & OMAP_BO_MEM_DMABUF) && omap_obj->sgt->nents == 1) ++ if ((omap_obj->flags & OMAP_BO_MEM_DMABUF) && ++ omap_gem_sgt_is_contiguous(omap_obj->sgt, omap_obj->base.size)) + return true; + + return false; +@@ -1385,7 +1391,7 @@ + union omap_gem_size gsize; + + /* Without a DMM only physically contiguous buffers can be supported. */ +- if (sgt->orig_nents != 1 && !priv->has_dmm) ++ if (!omap_gem_sgt_is_contiguous(sgt, size) && !priv->has_dmm) + return ERR_PTR(-EINVAL); + + gsize.bytes = PAGE_ALIGN(size); +@@ -1399,7 +1405,7 @@ + + omap_obj->sgt = sgt; + +- if (sgt->orig_nents == 1) { ++ if (omap_gem_sgt_is_contiguous(sgt, size)) { + omap_obj->dma_addr = sg_dma_address(sgt->sgl); + } else { + /* Create pages list from sgt */ +diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c +--- a/drivers/gpu/drm/tidss/tidss_dispc.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/gpu/drm/tidss/tidss_dispc.c 2024-03-28 11:26:09.897017444 -0400 +@@ -322,6 +322,60 @@ + .vid_order = { 1, 0 }, + }; + ++const struct dispc_features dispc_am62a7_feats = { ++ /* ++ * if the code reaches dispc_mode_valid with VP1, ++ * it should return MODE_BAD. ++ */ ++ .max_pclk_khz = { ++ [DISPC_VP_TIED_OFF] = 0, ++ [DISPC_VP_DPI] = 165000, ++ }, ++ ++ .scaling = { ++ .in_width_max_5tap_rgb = 1280, ++ .in_width_max_3tap_rgb = 2560, ++ .in_width_max_5tap_yuv = 2560, ++ .in_width_max_3tap_yuv = 4096, ++ .upscale_limit = 16, ++ .downscale_limit_5tap = 4, ++ .downscale_limit_3tap = 2, ++ /* ++ * The max supported pixel inc value is 255. The value ++ * of pixel inc is calculated like this: 1+(xinc-1)*bpp. ++ * The maximum bpp of all formats supported by the HW ++ * is 8. So the maximum supported xinc value is 32, ++ * because 1+(32-1)*8 < 255 < 1+(33-1)*4. ++ */ ++ .xinc_max = 32, ++ }, ++ ++ .subrev = DISPC_AM62A7, ++ ++ .common = "common", ++ .common_regs = tidss_am65x_common_regs, ++ ++ .num_vps = 2, ++ .vp_name = { "vp1", "vp2" }, ++ .ovr_name = { "ovr1", "ovr2" }, ++ .vpclk_name = { "vp1", "vp2" }, ++ /* VP1 of the DSS in AM62A7 SoC is tied off internally */ ++ .vp_bus_type = { DISPC_VP_TIED_OFF, DISPC_VP_DPI }, ++ ++ .vp_feat = { .color = { ++ .has_ctm = true, ++ .gamma_size = 256, ++ .gamma_type = TIDSS_GAMMA_8BIT, ++ }, ++ }, ++ ++ .num_planes = 2, ++ /* note: vid is plane_id 0 and vidl1 is plane_id 1 */ ++ .vid_name = { "vid", "vidl1" }, ++ .vid_lite = { false, true, }, ++ .vid_order = { 1, 0 }, ++}; ++ + static const u16 *dispc_common_regmap; + + struct dss_vp_data { +@@ -824,6 +878,7 @@ + case DISPC_K2G: + return dispc_k2g_read_and_clear_irqstatus(dispc); + case DISPC_AM625: ++ case DISPC_AM62A7: + case DISPC_AM65X: + case DISPC_J721E: + return dispc_k3_read_and_clear_irqstatus(dispc); +@@ -840,6 +895,7 @@ + dispc_k2g_set_irqenable(dispc, mask); + break; + case DISPC_AM625: ++ case DISPC_AM62A7: + case DISPC_AM65X: + case DISPC_J721E: + dispc_k3_set_irqenable(dispc, mask); +@@ -1331,6 +1387,7 @@ + x, y, layer); + break; + case DISPC_AM625: ++ case DISPC_AM62A7: + case DISPC_AM65X: + dispc_am65x_ovr_set_plane(dispc, hw_plane, hw_videoport, + x, y, layer); +@@ -2250,6 +2307,7 @@ + dispc_k2g_plane_init(dispc); + break; + case DISPC_AM625: ++ case DISPC_AM62A7: + case DISPC_AM65X: + case DISPC_J721E: + dispc_k3_plane_init(dispc); +@@ -2357,6 +2415,7 @@ + dispc_k2g_vp_write_gamma_table(dispc, hw_videoport); + break; + case DISPC_AM625: ++ case DISPC_AM62A7: + case DISPC_AM65X: + dispc_am65x_vp_write_gamma_table(dispc, hw_videoport); + break; +diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h +--- a/drivers/gpu/drm/tidss/tidss_dispc.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/gpu/drm/tidss/tidss_dispc.h 2024-03-28 11:26:09.897017444 -0400 +@@ -54,12 +54,14 @@ + DISPC_VP_DPI, /* DPI output */ + DISPC_VP_OLDI, /* OLDI (LVDS) output */ + DISPC_VP_INTERNAL, /* SoC internal routing */ ++ DISPC_VP_TIED_OFF, /* Tied off / Unavailable */ + DISPC_VP_MAX_BUS_TYPE, + }; + + enum dispc_dss_subrevision { + DISPC_K2G, + DISPC_AM625, ++ DISPC_AM62A7, + DISPC_AM65X, + DISPC_J721E, + }; +@@ -88,6 +90,7 @@ + + extern const struct dispc_features dispc_k2g_feats; + extern const struct dispc_features dispc_am625_feats; ++extern const struct dispc_features dispc_am62a7_feats; + extern const struct dispc_features dispc_am65x_feats; + extern const struct dispc_features dispc_j721e_feats; + +diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c +--- a/drivers/gpu/drm/tidss/tidss_drv.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/gpu/drm/tidss/tidss_drv.c 2024-03-28 11:26:09.897017444 -0400 +@@ -231,6 +231,7 @@ + static const struct of_device_id tidss_of_table[] = { + { .compatible = "ti,k2g-dss", .data = &dispc_k2g_feats, }, + { .compatible = "ti,am625-dss", .data = &dispc_am625_feats, }, ++ { .compatible = "ti,am62a7-dss", .data = &dispc_am62a7_feats, }, + { .compatible = "ti,am65x-dss", .data = &dispc_am65x_feats, }, + { .compatible = "ti,j721e-dss", .data = &dispc_j721e_feats, }, + { } +diff -Naur --no-dereference a/drivers/greybus/gb-beagleplay.c b/drivers/greybus/gb-beagleplay.c +--- a/drivers/greybus/gb-beagleplay.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/greybus/gb-beagleplay.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,501 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Beagleplay Linux Driver for Greybus ++ * ++ * Copyright (c) 2023 Ayush Singh ++ * Copyright (c) 2023 BeagleBoard.org Foundation ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RX_HDLC_PAYLOAD 256 ++#define CRC_LEN 2 ++#define MAX_RX_HDLC (1 + RX_HDLC_PAYLOAD + CRC_LEN) ++#define TX_CIRC_BUF_SIZE 1024 ++ ++#define ADDRESS_GREYBUS 0x01 ++#define ADDRESS_DBG 0x02 ++#define ADDRESS_CONTROL 0x03 ++ ++#define HDLC_FRAME 0x7E ++#define HDLC_ESC 0x7D ++#define HDLC_XOR 0x20 ++ ++#define CONTROL_SVC_START 0x01 ++#define CONTROL_SVC_STOP 0x02 ++ ++/* The maximum number of CPorts supported by Greybus Host Device */ ++#define GB_MAX_CPORTS 32 ++ ++/** ++ * struct gb_beagleplay - BeaglePlay Greybus driver ++ * ++ * @sd: underlying serdev device ++ * ++ * @gb_hd: greybus host device ++ * ++ * @tx_work: hdlc transmit work ++ * @tx_producer_lock: hdlc transmit data producer lock. acquired when appending data to buffer. ++ * @tx_consumer_lock: hdlc transmit data consumer lock. acquired when sending data over uart. ++ * @tx_circ_buf: hdlc transmit circular buffer. ++ * @tx_crc: hdlc transmit crc-ccitt fcs ++ * ++ * @rx_buffer_len: length of receive buffer filled. ++ * @rx_buffer: hdlc frame receive buffer ++ * @rx_in_esc: hdlc rx flag to indicate ESC frame ++ */ ++struct gb_beagleplay { ++ struct serdev_device *sd; ++ ++ struct gb_host_device *gb_hd; ++ ++ struct work_struct tx_work; ++ spinlock_t tx_producer_lock; ++ spinlock_t tx_consumer_lock; ++ struct circ_buf tx_circ_buf; ++ u16 tx_crc; ++ ++ u16 rx_buffer_len; ++ bool rx_in_esc; ++ u8 rx_buffer[MAX_RX_HDLC]; ++}; ++ ++/** ++ * struct hdlc_payload - Structure to represent part of HDCL frame payload data. ++ * ++ * @len: buffer length in bytes ++ * @buf: payload buffer ++ */ ++struct hdlc_payload { ++ u16 len; ++ void *buf; ++}; ++ ++static void hdlc_rx_greybus_frame(struct gb_beagleplay *bg, u8 *buf, u16 len) ++{ ++ u16 cport_id; ++ struct gb_operation_msg_hdr *hdr = (struct gb_operation_msg_hdr *)buf; ++ ++ memcpy(&cport_id, hdr->pad, sizeof(cport_id)); ++ ++ dev_dbg(&bg->sd->dev, "Greybus Operation %u type %X cport %u status %u received", ++ hdr->operation_id, hdr->type, cport_id, hdr->result); ++ ++ greybus_data_rcvd(bg->gb_hd, cport_id, buf, len); ++} ++ ++static void hdlc_rx_dbg_frame(const struct gb_beagleplay *bg, const char *buf, u16 len) ++{ ++ dev_dbg(&bg->sd->dev, "CC1352 Log: %.*s", (int)len, buf); ++} ++ ++/** ++ * hdlc_write() - Consume HDLC Buffer. ++ * @bg: beagleplay greybus driver ++ * ++ * Assumes that consumer lock has been acquired. ++ */ ++static void hdlc_write(struct gb_beagleplay *bg) ++{ ++ int written; ++ /* Start consuming HDLC data */ ++ int head = smp_load_acquire(&bg->tx_circ_buf.head); ++ int tail = bg->tx_circ_buf.tail; ++ int count = CIRC_CNT_TO_END(head, tail, TX_CIRC_BUF_SIZE); ++ const unsigned char *buf = &bg->tx_circ_buf.buf[tail]; ++ ++ if (count > 0) { ++ written = serdev_device_write_buf(bg->sd, buf, count); ++ ++ /* Finish consuming HDLC data */ ++ smp_store_release(&bg->tx_circ_buf.tail, (tail + written) & (TX_CIRC_BUF_SIZE - 1)); ++ } ++} ++ ++/** ++ * hdlc_append() - Queue HDLC data for sending. ++ * @bg: beagleplay greybus driver ++ * @value: hdlc byte to transmit ++ * ++ * Assumes that producer lock as been acquired. ++ */ ++static void hdlc_append(struct gb_beagleplay *bg, u8 value) ++{ ++ int tail, head = bg->tx_circ_buf.head; ++ ++ while (true) { ++ tail = READ_ONCE(bg->tx_circ_buf.tail); ++ ++ if (CIRC_SPACE(head, tail, TX_CIRC_BUF_SIZE) >= 1) { ++ bg->tx_circ_buf.buf[head] = value; ++ ++ /* Finish producing HDLC byte */ ++ smp_store_release(&bg->tx_circ_buf.head, ++ (head + 1) & (TX_CIRC_BUF_SIZE - 1)); ++ return; ++ } ++ dev_warn(&bg->sd->dev, "Tx circ buf full"); ++ usleep_range(3000, 5000); ++ } ++} ++ ++static void hdlc_append_escaped(struct gb_beagleplay *bg, u8 value) ++{ ++ if (value == HDLC_FRAME || value == HDLC_ESC) { ++ hdlc_append(bg, HDLC_ESC); ++ value ^= HDLC_XOR; ++ } ++ hdlc_append(bg, value); ++} ++ ++static void hdlc_append_tx_frame(struct gb_beagleplay *bg) ++{ ++ bg->tx_crc = 0xFFFF; ++ hdlc_append(bg, HDLC_FRAME); ++} ++ ++static void hdlc_append_tx_u8(struct gb_beagleplay *bg, u8 value) ++{ ++ bg->tx_crc = crc_ccitt(bg->tx_crc, &value, 1); ++ hdlc_append_escaped(bg, value); ++} ++ ++static void hdlc_append_tx_buf(struct gb_beagleplay *bg, const u8 *buf, u16 len) ++{ ++ size_t i; ++ ++ for (i = 0; i < len; i++) ++ hdlc_append_tx_u8(bg, buf[i]); ++} ++ ++static void hdlc_append_tx_crc(struct gb_beagleplay *bg) ++{ ++ bg->tx_crc ^= 0xffff; ++ hdlc_append_escaped(bg, bg->tx_crc & 0xff); ++ hdlc_append_escaped(bg, (bg->tx_crc >> 8) & 0xff); ++} ++ ++static void hdlc_transmit(struct work_struct *work) ++{ ++ struct gb_beagleplay *bg = container_of(work, struct gb_beagleplay, tx_work); ++ ++ spin_lock_bh(&bg->tx_consumer_lock); ++ hdlc_write(bg); ++ spin_unlock_bh(&bg->tx_consumer_lock); ++} ++ ++static void hdlc_tx_frames(struct gb_beagleplay *bg, u8 address, u8 control, ++ const struct hdlc_payload payloads[], size_t count) ++{ ++ size_t i; ++ ++ spin_lock(&bg->tx_producer_lock); ++ ++ hdlc_append_tx_frame(bg); ++ hdlc_append_tx_u8(bg, address); ++ hdlc_append_tx_u8(bg, control); ++ ++ for (i = 0; i < count; ++i) ++ hdlc_append_tx_buf(bg, payloads[i].buf, payloads[i].len); ++ ++ hdlc_append_tx_crc(bg); ++ hdlc_append_tx_frame(bg); ++ ++ spin_unlock(&bg->tx_producer_lock); ++ ++ schedule_work(&bg->tx_work); ++} ++ ++static void hdlc_tx_s_frame_ack(struct gb_beagleplay *bg) ++{ ++ hdlc_tx_frames(bg, bg->rx_buffer[0], (bg->rx_buffer[1] >> 1) & 0x7, NULL, 0); ++} ++ ++static void hdlc_rx_frame(struct gb_beagleplay *bg) ++{ ++ u16 crc, len; ++ u8 ctrl, *buf; ++ u8 address = bg->rx_buffer[0]; ++ ++ crc = crc_ccitt(0xffff, bg->rx_buffer, bg->rx_buffer_len); ++ if (crc != 0xf0b8) { ++ dev_warn_ratelimited(&bg->sd->dev, "CRC failed from %02x: 0x%04x", address, crc); ++ return; ++ } ++ ++ ctrl = bg->rx_buffer[1]; ++ buf = &bg->rx_buffer[2]; ++ len = bg->rx_buffer_len - 4; ++ ++ /* I-Frame, send S-Frame ACK */ ++ if ((ctrl & 1) == 0) ++ hdlc_tx_s_frame_ack(bg); ++ ++ switch (address) { ++ case ADDRESS_DBG: ++ hdlc_rx_dbg_frame(bg, buf, len); ++ break; ++ case ADDRESS_GREYBUS: ++ hdlc_rx_greybus_frame(bg, buf, len); ++ break; ++ default: ++ dev_warn_ratelimited(&bg->sd->dev, "unknown frame %u", address); ++ } ++} ++ ++static int hdlc_rx(struct gb_beagleplay *bg, const u8 *data, size_t count) ++{ ++ size_t i; ++ u8 c; ++ ++ for (i = 0; i < count; ++i) { ++ c = data[i]; ++ ++ switch (c) { ++ case HDLC_FRAME: ++ if (bg->rx_buffer_len) ++ hdlc_rx_frame(bg); ++ ++ bg->rx_buffer_len = 0; ++ break; ++ case HDLC_ESC: ++ bg->rx_in_esc = true; ++ break; ++ default: ++ if (bg->rx_in_esc) { ++ c ^= 0x20; ++ bg->rx_in_esc = false; ++ } ++ ++ if (bg->rx_buffer_len < MAX_RX_HDLC) { ++ bg->rx_buffer[bg->rx_buffer_len] = c; ++ bg->rx_buffer_len++; ++ } else { ++ dev_err_ratelimited(&bg->sd->dev, "RX Buffer Overflow"); ++ bg->rx_buffer_len = 0; ++ } ++ } ++ } ++ ++ return count; ++} ++ ++static int hdlc_init(struct gb_beagleplay *bg) ++{ ++ INIT_WORK(&bg->tx_work, hdlc_transmit); ++ spin_lock_init(&bg->tx_producer_lock); ++ spin_lock_init(&bg->tx_consumer_lock); ++ bg->tx_circ_buf.head = 0; ++ bg->tx_circ_buf.tail = 0; ++ ++ bg->tx_circ_buf.buf = devm_kmalloc(&bg->sd->dev, TX_CIRC_BUF_SIZE, GFP_KERNEL); ++ if (!bg->tx_circ_buf.buf) ++ return -ENOMEM; ++ ++ bg->rx_buffer_len = 0; ++ bg->rx_in_esc = false; ++ ++ return 0; ++} ++ ++static void hdlc_deinit(struct gb_beagleplay *bg) ++{ ++ flush_work(&bg->tx_work); ++} ++ ++static int gb_tty_receive(struct serdev_device *sd, const unsigned char *data, size_t count) ++{ ++ struct gb_beagleplay *bg = serdev_device_get_drvdata(sd); ++ ++ return hdlc_rx(bg, data, count); ++} ++ ++static void gb_tty_wakeup(struct serdev_device *serdev) ++{ ++ struct gb_beagleplay *bg = serdev_device_get_drvdata(serdev); ++ ++ schedule_work(&bg->tx_work); ++} ++ ++static struct serdev_device_ops gb_beagleplay_ops = { ++ .receive_buf = gb_tty_receive, ++ .write_wakeup = gb_tty_wakeup, ++}; ++ ++static int gb_message_send(struct gb_host_device *hd, u16 cport, struct gb_message *msg, gfp_t mask) ++{ ++ struct gb_beagleplay *bg = dev_get_drvdata(&hd->dev); ++ struct hdlc_payload payloads[2]; ++ ++ dev_dbg(&hd->dev, "Sending greybus message with Operation %u, Type: %X on Cport %u", ++ msg->header->operation_id, msg->header->type, cport); ++ ++ if (msg->header->size > RX_HDLC_PAYLOAD) ++ return dev_err_probe(&hd->dev, -E2BIG, "Greybus message too big"); ++ ++ memcpy(msg->header->pad, &cport, sizeof(cport)); ++ ++ payloads[0].buf = msg->header; ++ payloads[0].len = sizeof(*msg->header); ++ payloads[1].buf = msg->payload; ++ payloads[1].len = msg->payload_size; ++ ++ hdlc_tx_frames(bg, ADDRESS_GREYBUS, 0x03, payloads, 2); ++ greybus_message_sent(bg->gb_hd, msg, 0); ++ ++ return 0; ++} ++ ++static void gb_message_cancel(struct gb_message *message) ++{ ++} ++ ++static struct gb_hd_driver gb_hdlc_driver = { .message_send = gb_message_send, ++ .message_cancel = gb_message_cancel }; ++ ++static void gb_beagleplay_start_svc(struct gb_beagleplay *bg) ++{ ++ const u8 command = CONTROL_SVC_START; ++ const struct hdlc_payload payload = { .len = 1, .buf = (void *)&command }; ++ ++ hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1); ++} ++ ++static void gb_beagleplay_stop_svc(struct gb_beagleplay *bg) ++{ ++ const u8 command = CONTROL_SVC_STOP; ++ const struct hdlc_payload payload = { .len = 1, .buf = (void *)&command }; ++ ++ hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1); ++} ++ ++static void gb_greybus_deinit(struct gb_beagleplay *bg) ++{ ++ gb_hd_del(bg->gb_hd); ++ gb_hd_put(bg->gb_hd); ++} ++ ++static int gb_greybus_init(struct gb_beagleplay *bg) ++{ ++ int ret; ++ ++ bg->gb_hd = gb_hd_create(&gb_hdlc_driver, &bg->sd->dev, TX_CIRC_BUF_SIZE, GB_MAX_CPORTS); ++ if (IS_ERR(bg->gb_hd)) { ++ dev_err(&bg->sd->dev, "Failed to create greybus host device"); ++ return PTR_ERR(bg->gb_hd); ++ } ++ ++ ret = gb_hd_add(bg->gb_hd); ++ if (ret) { ++ dev_err(&bg->sd->dev, "Failed to add greybus host device"); ++ goto free_gb_hd; ++ } ++ dev_set_drvdata(&bg->gb_hd->dev, bg); ++ ++ return 0; ++ ++free_gb_hd: ++ gb_greybus_deinit(bg); ++ return ret; ++} ++ ++static void gb_serdev_deinit(struct gb_beagleplay *bg) ++{ ++ serdev_device_close(bg->sd); ++} ++ ++static int gb_serdev_init(struct gb_beagleplay *bg) ++{ ++ int ret; ++ ++ serdev_device_set_drvdata(bg->sd, bg); ++ serdev_device_set_client_ops(bg->sd, &gb_beagleplay_ops); ++ ret = serdev_device_open(bg->sd); ++ if (ret) ++ return dev_err_probe(&bg->sd->dev, ret, "Unable to open serial device"); ++ ++ serdev_device_set_baudrate(bg->sd, 115200); ++ serdev_device_set_flow_control(bg->sd, false); ++ ++ return 0; ++} ++ ++static int gb_beagleplay_probe(struct serdev_device *serdev) ++{ ++ int ret = 0; ++ struct gb_beagleplay *bg; ++ ++ bg = devm_kmalloc(&serdev->dev, sizeof(*bg), GFP_KERNEL); ++ if (!bg) ++ return -ENOMEM; ++ ++ bg->sd = serdev; ++ ret = gb_serdev_init(bg); ++ if (ret) ++ return ret; ++ ++ ret = hdlc_init(bg); ++ if (ret) ++ goto free_serdev; ++ ++ ret = gb_greybus_init(bg); ++ if (ret) ++ goto free_hdlc; ++ ++ gb_beagleplay_start_svc(bg); ++ ++ return 0; ++ ++free_hdlc: ++ hdlc_deinit(bg); ++free_serdev: ++ gb_serdev_deinit(bg); ++ return ret; ++} ++ ++static void gb_beagleplay_remove(struct serdev_device *serdev) ++{ ++ struct gb_beagleplay *bg = serdev_device_get_drvdata(serdev); ++ ++ gb_greybus_deinit(bg); ++ gb_beagleplay_stop_svc(bg); ++ hdlc_deinit(bg); ++ gb_serdev_deinit(bg); ++} ++ ++static const struct of_device_id gb_beagleplay_of_match[] = { ++ { ++ .compatible = "ti,cc1352p7", ++ }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, gb_beagleplay_of_match); ++ ++static struct serdev_device_driver gb_beagleplay_driver = { ++ .probe = gb_beagleplay_probe, ++ .remove = gb_beagleplay_remove, ++ .driver = { ++ .name = "gb_beagleplay", ++ .of_match_table = gb_beagleplay_of_match, ++ }, ++}; ++ ++module_serdev_device_driver(gb_beagleplay_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Ayush Singh "); ++MODULE_DESCRIPTION("A Greybus driver for BeaglePlay"); +diff -Naur --no-dereference a/drivers/greybus/Kconfig b/drivers/greybus/Kconfig +--- a/drivers/greybus/Kconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/greybus/Kconfig 2024-03-28 11:26:09.897017444 -0400 +@@ -17,6 +17,16 @@ + + if GREYBUS + ++config GREYBUS_BEAGLEPLAY ++ tristate "Greybus BeaglePlay driver" ++ depends on SERIAL_DEV_BUS ++ help ++ Select this option if you have a BeaglePlay where CC1352 ++ co-processor acts as Greybus SVC. ++ ++ To compile this code as a module, chose M here: the module ++ will be called gb-beagleplay.ko ++ + config GREYBUS_ES2 + tristate "Greybus ES3 USB host controller" + depends on USB +diff -Naur --no-dereference a/drivers/greybus/Makefile b/drivers/greybus/Makefile +--- a/drivers/greybus/Makefile 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/greybus/Makefile 2024-03-28 11:26:09.897017444 -0400 +@@ -18,6 +18,8 @@ + # needed for trace events + ccflags-y += -I$(src) + ++obj-$(CONFIG_GREYBUS_BEAGLEPLAY) += gb-beagleplay.o ++ + # Greybus Host controller drivers + gb-es2-y := es2.o + +diff -Naur --no-dereference a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c +--- a/drivers/input/touchscreen/edt-ft5x06.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/input/touchscreen/edt-ft5x06.c 2024-03-28 11:26:09.897017444 -0400 +@@ -69,6 +69,7 @@ + #define TOUCH_EVENT_RESERVED 0x03 + + #define EDT_NAME_LEN 23 ++#define EDT_NAME_PREFIX_LEN 8 + #define EDT_SWITCH_MODE_RETRIES 10 + #define EDT_SWITCH_MODE_DELAY 5 /* msec */ + #define EDT_RAW_DATA_RETRIES 100 +@@ -80,6 +81,10 @@ + #define M06_REG_CMD(factory) ((factory) ? 0xf3 : 0xfc) + #define M06_REG_ADDR(factory, addr) ((factory) ? (addr) & 0x7f : (addr) & 0x3f) + ++#define RESET_DELAY_MS 300 /* reset deassert to I2C */ ++#define FIRST_POLL_DELAY_MS 300 /* in addition to the above */ ++#define POLL_INTERVAL_MS 17 /* 17ms = 60fps */ ++ + enum edt_pmode { + EDT_PMODE_NOT_SUPPORTED, + EDT_PMODE_HIBERNATE, +@@ -139,14 +144,19 @@ + u8 tdata_cmd; + int tdata_len; + int tdata_offset; ++ unsigned int known_ids; + +- char name[EDT_NAME_LEN]; ++ char name[EDT_NAME_PREFIX_LEN + EDT_NAME_LEN]; + char fw_version[EDT_NAME_LEN]; ++ int init_td_status; + + struct edt_reg_addr reg_addr; + enum edt_ver version; + unsigned int crc_errors; + unsigned int header_errors; ++ ++ struct timer_list timer; ++ struct work_struct work_i2c_poll; + }; + + struct edt_i2c_chip_data { +@@ -303,17 +313,49 @@ + u8 rdbuf[63]; + int i, type, x, y, id; + int error; ++ int num_points; ++ unsigned int active_ids = 0, known_ids = tsdata->known_ids; ++ long released_ids; ++ int b = 0; + + memset(rdbuf, 0, sizeof(rdbuf)); + error = regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd, rdbuf, + tsdata->tdata_len); ++ if (tsdata->version == EDT_M06) { ++ num_points = tsdata->max_support_points; ++ } else { ++ /* Register 2 is TD_STATUS, containing the number of touch ++ * points. ++ */ ++ num_points = min(rdbuf[2] & 0xf, tsdata->max_support_points); ++ ++ /* When polling FT5x06 without IRQ: initial register contents ++ * could be stale or undefined; discard all readings until ++ * TD_STATUS changes for the first time (or num_points is 0). ++ */ ++ if (tsdata->init_td_status) { ++ if (tsdata->init_td_status < 0) ++ tsdata->init_td_status = rdbuf[2]; ++ ++ if (num_points && rdbuf[2] == tsdata->init_td_status) ++ goto out; ++ ++ tsdata->init_td_status = 0; ++ } ++ ++ if (!error && num_points) ++ error = regmap_bulk_read(tsdata->regmap, ++ tsdata->tdata_offset, ++ &rdbuf[tsdata->tdata_offset], ++ tsdata->point_len * num_points); ++ } + if (error) { + dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n", + error); + goto out; + } + +- for (i = 0; i < tsdata->max_support_points; i++) { ++ for (i = 0; i < num_points; i++) { + u8 *buf = &rdbuf[i * tsdata->point_len + tsdata->tdata_offset]; + + type = buf[0] >> 6; +@@ -335,10 +377,25 @@ + + input_mt_slot(tsdata->input, id); + if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, +- type != TOUCH_EVENT_UP)) ++ type != TOUCH_EVENT_UP)) { + touchscreen_report_pos(tsdata->input, &tsdata->prop, + x, y, true); ++ active_ids |= BIT(id); ++ } else { ++ known_ids &= ~BIT(id); ++ } ++ } ++ ++ /* One issue with the device is the TOUCH_UP message is not always ++ * returned. Instead track which ids we know about and report when they ++ * are no longer updated ++ */ ++ released_ids = known_ids & ~active_ids; ++ for_each_set_bit_from(b, &released_ids, tsdata->max_support_points) { ++ input_mt_slot(tsdata->input, b); ++ input_mt_report_slot_inactive(tsdata->input); + } ++ tsdata->known_ids = active_ids; + + input_mt_report_pointer_emulation(tsdata->input, true); + input_sync(tsdata->input); +@@ -347,6 +404,22 @@ + return IRQ_HANDLED; + } + ++static void edt_ft5x06_ts_irq_poll_timer(struct timer_list *t) ++{ ++ struct edt_ft5x06_ts_data *tsdata = from_timer(tsdata, t, timer); ++ ++ schedule_work(&tsdata->work_i2c_poll); ++ mod_timer(&tsdata->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS)); ++} ++ ++static void edt_ft5x06_ts_work_i2c_poll(struct work_struct *work) ++{ ++ struct edt_ft5x06_ts_data *tsdata = container_of(work, ++ struct edt_ft5x06_ts_data, work_i2c_poll); ++ ++ edt_ft5x06_ts_isr(0, tsdata); ++} ++ + struct edt_ft5x06_attribute { + struct device_attribute dattr; + size_t field_offset; +@@ -865,6 +938,9 @@ + char *model_name = tsdata->name; + char *fw_version = tsdata->fw_version; + ++ snprintf(model_name, EDT_NAME_PREFIX_LEN + 1, "%s ", dev_name(&client->dev)); ++ model_name += strlen(model_name); ++ + /* see what we find if we assume it is a M06 * + * if we get less than EDT_NAME_LEN, we don't want + * to have garbage in there +@@ -1053,20 +1129,23 @@ + static void edt_ft5x06_ts_set_tdata_parameters(struct edt_ft5x06_ts_data *tsdata) + { + int crclen; ++ int points; + + if (tsdata->version == EDT_M06) { + tsdata->tdata_cmd = 0xf9; + tsdata->tdata_offset = 5; + tsdata->point_len = 4; + crclen = 1; ++ points = tsdata->max_support_points; + } else { + tsdata->tdata_cmd = 0x0; + tsdata->tdata_offset = 3; + tsdata->point_len = 6; + crclen = 0; ++ points = 0; + } + +- tsdata->tdata_len = tsdata->point_len * tsdata->max_support_points + ++ tsdata->tdata_len = tsdata->point_len * points + + tsdata->tdata_offset + crclen; + } + +@@ -1243,7 +1322,7 @@ + if (tsdata->reset_gpio) { + usleep_range(5000, 6000); + gpiod_set_value_cansleep(tsdata->reset_gpio, 0); +- msleep(300); ++ msleep(RESET_DELAY_MS); + } + + input = devm_input_allocate_device(&client->dev); +@@ -1317,17 +1396,28 @@ + return error; + } + +- irq_flags = irq_get_trigger_type(client->irq); +- if (irq_flags == IRQF_TRIGGER_NONE) +- irq_flags = IRQF_TRIGGER_FALLING; +- irq_flags |= IRQF_ONESHOT; +- +- error = devm_request_threaded_irq(&client->dev, client->irq, +- NULL, edt_ft5x06_ts_isr, irq_flags, +- client->name, tsdata); +- if (error) { +- dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); +- return error; ++ if (client->irq) { ++ irq_flags = irq_get_trigger_type(client->irq); ++ if (irq_flags == IRQF_TRIGGER_NONE) ++ irq_flags = IRQF_TRIGGER_FALLING; ++ irq_flags |= IRQF_ONESHOT; ++ ++ error = devm_request_threaded_irq(&client->dev, client->irq, ++ NULL, edt_ft5x06_ts_isr, ++ irq_flags, client->name, ++ tsdata); ++ if (error) { ++ dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); ++ return error; ++ } ++ } else { ++ tsdata->init_td_status = -1; /* filter bogus initial data */ ++ INIT_WORK(&tsdata->work_i2c_poll, ++ edt_ft5x06_ts_work_i2c_poll); ++ timer_setup(&tsdata->timer, edt_ft5x06_ts_irq_poll_timer, 0); ++ tsdata->timer.expires = ++ jiffies + msecs_to_jiffies(FIRST_POLL_DELAY_MS); ++ add_timer(&tsdata->timer); + } + + error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group); +@@ -1353,6 +1443,10 @@ + { + struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); + ++ if (!client->irq) { ++ del_timer(&tsdata->timer); ++ cancel_work_sync(&tsdata->work_i2c_poll); ++ } + edt_ft5x06_ts_teardown_debugfs(tsdata); + regmap_exit(tsdata->regmap); + } +diff -Naur --no-dereference a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c +--- a/drivers/media/platform/cadence/cdns-csi2rx.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/cadence/cdns-csi2rx.c 2024-03-28 11:26:09.897017444 -0400 +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -40,10 +41,14 @@ + #define CSI2RX_STREAM_BASE(n) (((n) + 1) * 0x100) + + #define CSI2RX_STREAM_CTRL_REG(n) (CSI2RX_STREAM_BASE(n) + 0x000) ++#define CSI2RX_STREAM_CTRL_SOFT_RST BIT(4) ++#define CSI2RX_STREAM_CTRL_STOP BIT(1) + #define CSI2RX_STREAM_CTRL_START BIT(0) + ++#define CSI2RX_STREAM_STATUS_REG(n) (CSI2RX_STREAM_BASE(n) + 0x004) ++#define CSI2RX_STREAM_STATUS_RDY BIT(31) ++ + #define CSI2RX_STREAM_DATA_CFG_REG(n) (CSI2RX_STREAM_BASE(n) + 0x008) +-#define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT BIT(31) + #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n) BIT((n) + 16) + + #define CSI2RX_STREAM_CFG_REG(n) (CSI2RX_STREAM_BASE(n) + 0x00c) +@@ -61,6 +66,11 @@ + CSI2RX_PAD_MAX, + }; + ++struct csi2rx_fmt { ++ u32 code; ++ u8 bpp; ++}; ++ + struct csi2rx_priv { + struct device *dev; + unsigned int count; +@@ -95,6 +105,36 @@ + int source_pad; + }; + ++static const struct csi2rx_fmt formats[] = { ++ { .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, }, ++ { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, }, ++ { .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, }, ++ { .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, }, ++ { .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, }, ++ { .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, }, ++ { .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, }, ++ { .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, }, ++ { .code = MEDIA_BUS_FMT_Y8_1X8, .bpp = 8, }, ++ { .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, }, ++ { .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, }, ++ { .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, }, ++ { .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, }, ++ { .code = MEDIA_BUS_FMT_RGB565_1X16, .bpp = 16, }, ++ { .code = MEDIA_BUS_FMT_RGB888_1X24, .bpp = 24, }, ++ { .code = MEDIA_BUS_FMT_BGR888_1X24, .bpp = 24, }, ++}; ++ ++static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(formats); i++) ++ if (formats[i].code == code) ++ return &formats[i]; ++ ++ return NULL; ++} ++ + static inline + struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev) + { +@@ -103,19 +143,54 @@ + + static void csi2rx_reset(struct csi2rx_priv *csi2rx) + { ++ unsigned int i; ++ ++ /* Reset module */ + writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT, + csi2rx->base + CSI2RX_SOFT_RESET_REG); ++ /* Reset individual streams. */ ++ for (i = 0; i < csi2rx->max_streams; i++) { ++ writel(CSI2RX_STREAM_CTRL_SOFT_RST, ++ csi2rx->base + CSI2RX_STREAM_CTRL_REG(i)); ++ } + +- udelay(10); ++ usleep_range(10, 20); + ++ /* Clear resets */ + writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG); ++ for (i = 0; i < csi2rx->max_streams; i++) ++ writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i)); + } + + static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx) + { + union phy_configure_opts opts = { }; ++ struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy; ++ struct v4l2_subdev_format sd_fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .pad = CSI2RX_PAD_SINK, ++ }; ++ const struct csi2rx_fmt *fmt; ++ s64 link_freq; + int ret; + ++ ret = v4l2_subdev_call_state_active(&csi2rx->subdev, pad, get_fmt, ++ &sd_fmt); ++ if (ret < 0) ++ return ret; ++ ++ fmt = csi2rx_get_fmt_by_code(sd_fmt.format.code); ++ ++ link_freq = v4l2_get_link_freq(csi2rx->source_subdev->ctrl_handler, ++ fmt->bpp, 2 * csi2rx->num_lanes); ++ if (link_freq < 0) ++ return link_freq; ++ ++ ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq, ++ csi2rx->num_lanes, cfg); ++ if (ret) ++ return ret; ++ + ret = phy_power_on(csi2rx->dphy); + if (ret) + return ret; +@@ -199,8 +274,11 @@ + writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF, + csi2rx->base + CSI2RX_STREAM_CFG_REG(i)); + +- writel(CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT | +- CSI2RX_STREAM_DATA_CFG_VC_SELECT(i), ++ /* ++ * Enable one virtual channel. When multiple virtual channels ++ * are supported this will have to be changed. ++ */ ++ writel(CSI2RX_STREAM_DATA_CFG_VC_SELECT(0), + csi2rx->base + CSI2RX_STREAM_DATA_CFG_REG(i)); + + writel(CSI2RX_STREAM_CTRL_START, +@@ -243,13 +321,25 @@ + static void csi2rx_stop(struct csi2rx_priv *csi2rx) + { + unsigned int i; ++ u32 val; ++ int ret; + + clk_prepare_enable(csi2rx->p_clk); + reset_control_assert(csi2rx->sys_rst); + clk_disable_unprepare(csi2rx->sys_clk); + + for (i = 0; i < csi2rx->max_streams; i++) { +- writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i)); ++ writel(CSI2RX_STREAM_CTRL_STOP, ++ csi2rx->base + CSI2RX_STREAM_CTRL_REG(i)); ++ ++ ret = readl_relaxed_poll_timeout(csi2rx->base + ++ CSI2RX_STREAM_STATUS_REG(i), ++ val, ++ !(val & CSI2RX_STREAM_STATUS_RDY), ++ 10, 10000); ++ if (ret) ++ dev_warn(csi2rx->dev, ++ "Failed to stop streaming on pad%u\n", i); + + reset_control_assert(csi2rx->pixel_rst[i]); + clk_disable_unprepare(csi2rx->pixel_clk[i]); +@@ -303,12 +393,72 @@ + return ret; + } + ++static int csi2rx_set_fmt(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_state *state, ++ struct v4l2_subdev_format *format) ++{ ++ struct v4l2_mbus_framefmt *fmt; ++ unsigned int i; ++ ++ /* No transcoding, source and sink formats must match. */ ++ if (format->pad != CSI2RX_PAD_SINK) ++ return v4l2_subdev_get_fmt(subdev, state, format); ++ ++ if (!csi2rx_get_fmt_by_code(format->format.code)) ++ format->format.code = formats[0].code; ++ ++ format->format.field = V4L2_FIELD_NONE; ++ ++ /* Set sink format */ ++ fmt = v4l2_subdev_get_pad_format(subdev, state, format->pad); ++ *fmt = format->format; ++ ++ /* Propagate to source formats */ ++ for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) { ++ fmt = v4l2_subdev_get_pad_format(subdev, state, i); ++ *fmt = format->format; ++ } ++ ++ return 0; ++} ++ ++static int csi2rx_init_cfg(struct v4l2_subdev *subdev, ++ struct v4l2_subdev_state *state) ++{ ++ struct v4l2_subdev_format format = { ++ .pad = CSI2RX_PAD_SINK, ++ .format = { ++ .width = 640, ++ .height = 480, ++ .code = MEDIA_BUS_FMT_UYVY8_1X16, ++ .field = V4L2_FIELD_NONE, ++ .colorspace = V4L2_COLORSPACE_SRGB, ++ .ycbcr_enc = V4L2_YCBCR_ENC_601, ++ .quantization = V4L2_QUANTIZATION_LIM_RANGE, ++ .xfer_func = V4L2_XFER_FUNC_SRGB, ++ }, ++ }; ++ ++ return csi2rx_set_fmt(subdev, state, &format); ++} ++ ++static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = { ++ .get_fmt = v4l2_subdev_get_fmt, ++ .set_fmt = csi2rx_set_fmt, ++ .init_cfg = csi2rx_init_cfg, ++}; ++ + static const struct v4l2_subdev_video_ops csi2rx_video_ops = { + .s_stream = csi2rx_s_stream, + }; + + static const struct v4l2_subdev_ops csi2rx_subdev_ops = { + .video = &csi2rx_video_ops, ++ .pad = &csi2rx_pad_ops, ++}; ++ ++static const struct media_entity_operations csi2rx_media_ops = { ++ .link_validate = v4l2_subdev_link_validate, + }; + + static int csi2rx_async_bound(struct v4l2_async_notifier *notifier, +@@ -319,7 +469,7 @@ + struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev); + + csi2rx->source_pad = media_entity_get_fwnode_pad(&s_subdev->entity, +- s_subdev->fwnode, ++ asd->match.fwnode, + MEDIA_PAD_FL_SOURCE); + if (csi2rx->source_pad < 0) { + dev_err(csi2rx->dev, "Couldn't find output pad for subdev %s\n", +@@ -526,15 +676,21 @@ + csi2rx->pads[CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK; + for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++) + csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE; ++ csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; ++ csi2rx->subdev.entity.ops = &csi2rx_media_ops; + + ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX, + csi2rx->pads); + if (ret) + goto err_cleanup; + ++ ret = v4l2_subdev_init_finalize(&csi2rx->subdev); ++ if (ret) ++ goto err_cleanup; ++ + ret = v4l2_async_register_subdev(&csi2rx->subdev); + if (ret < 0) +- goto err_cleanup; ++ goto err_free_state; + + dev_info(&pdev->dev, + "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n", +@@ -544,9 +700,12 @@ + + return 0; + ++err_free_state: ++ v4l2_subdev_cleanup(&csi2rx->subdev); + err_cleanup: + v4l2_async_nf_unregister(&csi2rx->notifier); + v4l2_async_nf_cleanup(&csi2rx->notifier); ++ media_entity_cleanup(&csi2rx->subdev.entity); + err_free_priv: + kfree(csi2rx); + return ret; +@@ -559,6 +718,8 @@ + v4l2_async_nf_unregister(&csi2rx->notifier); + v4l2_async_nf_cleanup(&csi2rx->notifier); + v4l2_async_unregister_subdev(&csi2rx->subdev); ++ v4l2_subdev_cleanup(&csi2rx->subdev); ++ media_entity_cleanup(&csi2rx->subdev.entity); + kfree(csi2rx); + } + +diff -Naur --no-dereference a/drivers/media/platform/cadence/Kconfig b/drivers/media/platform/cadence/Kconfig +--- a/drivers/media/platform/cadence/Kconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/cadence/Kconfig 2024-03-28 11:26:09.897017444 -0400 +@@ -8,6 +8,7 @@ + select MEDIA_CONTROLLER + select VIDEO_V4L2_SUBDEV_API + select V4L2_FWNODE ++ select GENERIC_PHY_MIPI_DPHY + help + Support for the Cadence MIPI CSI2 Receiver controller. + +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-bit.c b/drivers/media/platform/chips-media/coda/coda-bit.c +--- a/drivers/media/platform/chips-media/coda/coda-bit.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda-bit.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,2666 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Coda multi-standard codec IP - BIT processor functions ++ * ++ * Copyright (C) 2012 Vista Silicon S.L. ++ * Javier Martin, ++ * Xavier Duret ++ * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coda.h" ++#include "imx-vdoa.h" ++#define CREATE_TRACE_POINTS ++#include "trace.h" ++ ++#define CODA_PARA_BUF_SIZE (10 * 1024) ++#define CODA7_PS_BUF_SIZE 0x28000 ++#define CODA9_PS_SAVE_SIZE (512 * 1024) ++ ++#define CODA_DEFAULT_GAMMA 4096 ++#define CODA9_DEFAULT_GAMMA 24576 /* 0.75 * 32768 */ ++ ++static void coda_free_bitstream_buffer(struct coda_ctx *ctx); ++ ++static inline int coda_is_initialized(struct coda_dev *dev) ++{ ++ return coda_read(dev, CODA_REG_BIT_CUR_PC) != 0; ++} ++ ++static inline unsigned long coda_isbusy(struct coda_dev *dev) ++{ ++ return coda_read(dev, CODA_REG_BIT_BUSY); ++} ++ ++static int coda_wait_timeout(struct coda_dev *dev) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(1000); ++ ++ while (coda_isbusy(dev)) { ++ if (time_after(jiffies, timeout)) ++ return -ETIMEDOUT; ++ } ++ return 0; ++} ++ ++static void coda_command_async(struct coda_ctx *ctx, int cmd) ++{ ++ struct coda_dev *dev = ctx->dev; ++ ++ if (dev->devtype->product == CODA_HX4 || ++ dev->devtype->product == CODA_7541 || ++ dev->devtype->product == CODA_960) { ++ /* Restore context related registers to CODA */ ++ coda_write(dev, ctx->bit_stream_param, ++ CODA_REG_BIT_BIT_STREAM_PARAM); ++ coda_write(dev, ctx->frm_dis_flg, ++ CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); ++ coda_write(dev, ctx->frame_mem_ctrl, ++ CODA_REG_BIT_FRAME_MEM_CTRL); ++ coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); ++ } ++ ++ if (dev->devtype->product == CODA_960) { ++ coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); ++ coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); ++ } ++ ++ coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); ++ ++ coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); ++ coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD); ++ coda_write(dev, ctx->params.codec_mode_aux, CODA7_REG_BIT_RUN_AUX_STD); ++ ++ trace_coda_bit_run(ctx, cmd); ++ ++ coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); ++} ++ ++static int coda_command_sync(struct coda_ctx *ctx, int cmd) ++{ ++ struct coda_dev *dev = ctx->dev; ++ int ret; ++ ++ lockdep_assert_held(&dev->coda_mutex); ++ ++ coda_command_async(ctx, cmd); ++ ret = coda_wait_timeout(dev); ++ trace_coda_bit_done(ctx); ++ ++ return ret; ++} ++ ++int coda_hw_reset(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ unsigned long timeout; ++ unsigned int idx; ++ int ret; ++ ++ lockdep_assert_held(&dev->coda_mutex); ++ ++ if (!dev->rstc) ++ return -ENOENT; ++ ++ idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX); ++ ++ if (dev->devtype->product == CODA_960) { ++ timeout = jiffies + msecs_to_jiffies(100); ++ coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL); ++ while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) { ++ if (time_after(jiffies, timeout)) ++ return -ETIME; ++ cpu_relax(); ++ } ++ } ++ ++ ret = reset_control_reset(dev->rstc); ++ if (ret < 0) ++ return ret; ++ ++ if (dev->devtype->product == CODA_960) ++ coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL); ++ coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); ++ coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); ++ ret = coda_wait_timeout(dev); ++ coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX); ++ ++ return ret; ++} ++ ++static void coda_kfifo_sync_from_device(struct coda_ctx *ctx) ++{ ++ struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; ++ struct coda_dev *dev = ctx->dev; ++ u32 rd_ptr; ++ ++ rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); ++ kfifo->out = (kfifo->in & ~kfifo->mask) | ++ (rd_ptr - ctx->bitstream.paddr); ++ if (kfifo->out > kfifo->in) ++ kfifo->out -= kfifo->mask + 1; ++} ++ ++static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx) ++{ ++ struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; ++ struct coda_dev *dev = ctx->dev; ++ u32 rd_ptr, wr_ptr; ++ ++ rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask); ++ coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); ++ wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); ++ coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); ++} ++ ++static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx) ++{ ++ struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; ++ struct coda_dev *dev = ctx->dev; ++ u32 wr_ptr; ++ ++ wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); ++ coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); ++} ++ ++static int coda_h264_bitstream_pad(struct coda_ctx *ctx, u32 size) ++{ ++ unsigned char *buf; ++ u32 n; ++ ++ if (size < 6) ++ size = 6; ++ ++ buf = kmalloc(size, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ coda_h264_filler_nal(size, buf); ++ n = kfifo_in(&ctx->bitstream_fifo, buf, size); ++ kfree(buf); ++ ++ return (n < size) ? -ENOSPC : 0; ++} ++ ++int coda_bitstream_flush(struct coda_ctx *ctx) ++{ ++ int ret; ++ ++ if (ctx->inst_type != CODA_INST_DECODER || !ctx->use_bit) ++ return 0; ++ ++ ret = coda_command_sync(ctx, CODA_COMMAND_DEC_BUF_FLUSH); ++ if (ret < 0) { ++ v4l2_err(&ctx->dev->v4l2_dev, "failed to flush bitstream\n"); ++ return ret; ++ } ++ ++ kfifo_init(&ctx->bitstream_fifo, ctx->bitstream.vaddr, ++ ctx->bitstream.size); ++ coda_kfifo_sync_to_device_full(ctx); ++ ++ return 0; ++} ++ ++static int coda_bitstream_queue(struct coda_ctx *ctx, const u8 *buf, u32 size) ++{ ++ u32 n = kfifo_in(&ctx->bitstream_fifo, buf, size); ++ ++ return (n < size) ? -ENOSPC : 0; ++} ++ ++static u32 coda_buffer_parse_headers(struct coda_ctx *ctx, ++ struct vb2_v4l2_buffer *src_buf, ++ u32 payload) ++{ ++ u8 *vaddr = vb2_plane_vaddr(&src_buf->vb2_buf, 0); ++ u32 size = 0; ++ ++ switch (ctx->codec->src_fourcc) { ++ case V4L2_PIX_FMT_MPEG2: ++ size = coda_mpeg2_parse_headers(ctx, vaddr, payload); ++ break; ++ case V4L2_PIX_FMT_MPEG4: ++ size = coda_mpeg4_parse_headers(ctx, vaddr, payload); ++ break; ++ default: ++ break; ++ } ++ ++ return size; ++} ++ ++static bool coda_bitstream_try_queue(struct coda_ctx *ctx, ++ struct vb2_v4l2_buffer *src_buf) ++{ ++ unsigned long payload = vb2_get_plane_payload(&src_buf->vb2_buf, 0); ++ u8 *vaddr = vb2_plane_vaddr(&src_buf->vb2_buf, 0); ++ int ret; ++ int i; ++ ++ if (coda_get_bitstream_payload(ctx) + payload + 512 >= ++ ctx->bitstream.size) ++ return false; ++ ++ if (!vaddr) { ++ v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n"); ++ return true; ++ } ++ ++ if (ctx->qsequence == 0 && payload < 512) { ++ /* ++ * Add padding after the first buffer, if it is too small to be ++ * fetched by the CODA, by repeating the headers. Without ++ * repeated headers, or the first frame already queued, decoder ++ * sequence initialization fails with error code 0x2000 on i.MX6 ++ * or error code 0x1 on i.MX51. ++ */ ++ u32 header_size = coda_buffer_parse_headers(ctx, src_buf, ++ payload); ++ ++ if (header_size) { ++ coda_dbg(1, ctx, "pad with %u-byte header\n", ++ header_size); ++ for (i = payload; i < 512; i += header_size) { ++ ret = coda_bitstream_queue(ctx, vaddr, ++ header_size); ++ if (ret < 0) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "bitstream buffer overflow\n"); ++ return false; ++ } ++ if (ctx->dev->devtype->product == CODA_960) ++ break; ++ } ++ } else { ++ coda_dbg(1, ctx, ++ "could not parse header, sequence initialization might fail\n"); ++ } ++ ++ /* Add padding before the first buffer, if it is too small */ ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264) ++ coda_h264_bitstream_pad(ctx, 512 - payload); ++ } ++ ++ ret = coda_bitstream_queue(ctx, vaddr, payload); ++ if (ret < 0) { ++ v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n"); ++ return false; ++ } ++ ++ src_buf->sequence = ctx->qsequence++; ++ ++ /* Sync read pointer to device */ ++ if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev)) ++ coda_kfifo_sync_to_device_write(ctx); ++ ++ /* Set the stream-end flag after the last buffer is queued */ ++ if (src_buf->flags & V4L2_BUF_FLAG_LAST) ++ coda_bit_stream_end_flag(ctx); ++ ctx->hold = false; ++ ++ return true; ++} ++ ++void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list) ++{ ++ struct vb2_v4l2_buffer *src_buf; ++ struct coda_buffer_meta *meta; ++ u32 start; ++ ++ lockdep_assert_held(&ctx->bitstream_mutex); ++ ++ if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) ++ return; ++ ++ while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) { ++ /* ++ * Only queue two JPEGs into the bitstream buffer to keep ++ * latency low. We need at least one complete buffer and the ++ * header of another buffer (for prescan) in the bitstream. ++ */ ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG && ++ ctx->num_metas > 1) ++ break; ++ ++ if (ctx->num_internal_frames && ++ ctx->num_metas >= ctx->num_internal_frames) { ++ meta = list_first_entry(&ctx->buffer_meta_list, ++ struct coda_buffer_meta, list); ++ ++ /* ++ * If we managed to fill in at least a full reorder ++ * window of buffers (num_internal_frames is a ++ * conservative estimate for this) and the bitstream ++ * prefetcher has at least 2 256 bytes periods beyond ++ * the first buffer to fetch, we can safely stop queuing ++ * in order to limit the decoder drain latency. ++ */ ++ if (coda_bitstream_can_fetch_past(ctx, meta->end)) ++ break; ++ } ++ ++ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); ++ ++ /* Drop frames that do not start/end with a SOI/EOI markers */ ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG && ++ !coda_jpeg_check_buffer(ctx, &src_buf->vb2_buf)) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "dropping invalid JPEG frame %d\n", ++ ctx->qsequence); ++ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); ++ if (buffer_list) { ++ struct v4l2_m2m_buffer *m2m_buf; ++ ++ m2m_buf = container_of(src_buf, ++ struct v4l2_m2m_buffer, ++ vb); ++ list_add_tail(&m2m_buf->list, buffer_list); ++ } else { ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); ++ } ++ continue; ++ } ++ ++ /* Dump empty buffers */ ++ if (!vb2_get_plane_payload(&src_buf->vb2_buf, 0)) { ++ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ continue; ++ } ++ ++ /* Buffer start position */ ++ start = ctx->bitstream_fifo.kfifo.in; ++ ++ if (coda_bitstream_try_queue(ctx, src_buf)) { ++ /* ++ * Source buffer is queued in the bitstream ringbuffer; ++ * queue the timestamp and mark source buffer as done ++ */ ++ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); ++ ++ meta = kmalloc(sizeof(*meta), GFP_KERNEL); ++ if (meta) { ++ meta->sequence = src_buf->sequence; ++ meta->timecode = src_buf->timecode; ++ meta->timestamp = src_buf->vb2_buf.timestamp; ++ meta->start = start; ++ meta->end = ctx->bitstream_fifo.kfifo.in; ++ meta->last = src_buf->flags & V4L2_BUF_FLAG_LAST; ++ if (meta->last) ++ coda_dbg(1, ctx, "marking last meta"); ++ spin_lock(&ctx->buffer_meta_lock); ++ list_add_tail(&meta->list, ++ &ctx->buffer_meta_list); ++ ctx->num_metas++; ++ spin_unlock(&ctx->buffer_meta_lock); ++ ++ trace_coda_bit_queue(ctx, src_buf, meta); ++ } ++ ++ if (buffer_list) { ++ struct v4l2_m2m_buffer *m2m_buf; ++ ++ m2m_buf = container_of(src_buf, ++ struct v4l2_m2m_buffer, ++ vb); ++ list_add_tail(&m2m_buf->list, buffer_list); ++ } else { ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ } ++ } else { ++ break; ++ } ++ } ++} ++ ++void coda_bit_stream_end_flag(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ ++ ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; ++ ++ /* If this context is currently running, update the hardware flag */ ++ if ((dev->devtype->product == CODA_960) && ++ coda_isbusy(dev) && ++ (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) { ++ coda_write(dev, ctx->bit_stream_param, ++ CODA_REG_BIT_BIT_STREAM_PARAM); ++ } ++} ++ ++static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) ++{ ++ struct coda_dev *dev = ctx->dev; ++ u32 *p = ctx->parabuf.vaddr; ++ ++ if (dev->devtype->product == CODA_DX6) ++ p[index] = value; ++ else ++ p[index ^ 1] = value; ++} ++ ++static inline int coda_alloc_context_buf(struct coda_ctx *ctx, ++ struct coda_aux_buf *buf, size_t size, ++ const char *name) ++{ ++ return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry); ++} ++ ++ ++static void coda_free_framebuffers(struct coda_ctx *ctx) ++{ ++ int i; ++ ++ for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) ++ coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i].buf); ++} ++ ++static int coda_alloc_framebuffers(struct coda_ctx *ctx, ++ struct coda_q_data *q_data, u32 fourcc) ++{ ++ struct coda_dev *dev = ctx->dev; ++ unsigned int ysize, ycbcr_size; ++ int ret; ++ int i; ++ ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || ++ ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 || ++ ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 || ++ ctx->codec->dst_fourcc == V4L2_PIX_FMT_MPEG4) ++ ysize = round_up(q_data->rect.width, 16) * ++ round_up(q_data->rect.height, 16); ++ else ++ ysize = round_up(q_data->rect.width, 8) * q_data->rect.height; ++ ++ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) ++ ycbcr_size = round_up(ysize, 4096) + ysize / 2; ++ else ++ ycbcr_size = ysize + ysize / 2; ++ ++ /* Allocate frame buffers */ ++ for (i = 0; i < ctx->num_internal_frames; i++) { ++ size_t size = ycbcr_size; ++ char *name; ++ ++ /* Add space for mvcol buffers */ ++ if (dev->devtype->product != CODA_DX6 && ++ (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || ++ (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0))) ++ size += ysize / 4; ++ name = kasprintf(GFP_KERNEL, "fb%d", i); ++ if (!name) { ++ coda_free_framebuffers(ctx); ++ return -ENOMEM; ++ } ++ ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i].buf, ++ size, name); ++ kfree(name); ++ if (ret < 0) { ++ coda_free_framebuffers(ctx); ++ return ret; ++ } ++ } ++ ++ /* Register frame buffers in the parameter buffer */ ++ for (i = 0; i < ctx->num_internal_frames; i++) { ++ u32 y, cb, cr, mvcol; ++ ++ /* Start addresses of Y, Cb, Cr planes */ ++ y = ctx->internal_frames[i].buf.paddr; ++ cb = y + ysize; ++ cr = y + ysize + ysize/4; ++ mvcol = y + ysize + ysize/4 + ysize/4; ++ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) { ++ cb = round_up(cb, 4096); ++ mvcol = cb + ysize/2; ++ cr = 0; ++ /* Packed 20-bit MSB of base addresses */ ++ /* YYYYYCCC, CCyyyyyc, cccc.... */ ++ y = (y & 0xfffff000) | cb >> 20; ++ cb = (cb & 0x000ff000) << 12; ++ } ++ coda_parabuf_write(ctx, i * 3 + 0, y); ++ coda_parabuf_write(ctx, i * 3 + 1, cb); ++ coda_parabuf_write(ctx, i * 3 + 2, cr); ++ ++ if (dev->devtype->product == CODA_DX6) ++ continue; ++ ++ /* mvcol buffer for h.264 and mpeg4 */ ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264) ++ coda_parabuf_write(ctx, 96 + i, mvcol); ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0) ++ coda_parabuf_write(ctx, 97, mvcol); ++ } ++ ++ return 0; ++} ++ ++static void coda_free_context_buffers(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ ++ coda_free_aux_buf(dev, &ctx->slicebuf); ++ coda_free_aux_buf(dev, &ctx->psbuf); ++ if (dev->devtype->product != CODA_DX6) ++ coda_free_aux_buf(dev, &ctx->workbuf); ++ coda_free_aux_buf(dev, &ctx->parabuf); ++} ++ ++static int coda_alloc_context_buffers(struct coda_ctx *ctx, ++ struct coda_q_data *q_data) ++{ ++ struct coda_dev *dev = ctx->dev; ++ size_t size; ++ int ret; ++ ++ if (!ctx->parabuf.vaddr) { ++ ret = coda_alloc_context_buf(ctx, &ctx->parabuf, ++ CODA_PARA_BUF_SIZE, "parabuf"); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (dev->devtype->product == CODA_DX6) ++ return 0; ++ ++ if (!ctx->slicebuf.vaddr && q_data->fourcc == V4L2_PIX_FMT_H264) { ++ /* worst case slice size */ ++ size = (DIV_ROUND_UP(q_data->rect.width, 16) * ++ DIV_ROUND_UP(q_data->rect.height, 16)) * 3200 / 8 + 512; ++ ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size, ++ "slicebuf"); ++ if (ret < 0) ++ goto err; ++ } ++ ++ if (!ctx->psbuf.vaddr && (dev->devtype->product == CODA_HX4 || ++ dev->devtype->product == CODA_7541)) { ++ ret = coda_alloc_context_buf(ctx, &ctx->psbuf, ++ CODA7_PS_BUF_SIZE, "psbuf"); ++ if (ret < 0) ++ goto err; ++ } ++ ++ if (!ctx->workbuf.vaddr) { ++ size = dev->devtype->workbuf_size; ++ if (dev->devtype->product == CODA_960 && ++ q_data->fourcc == V4L2_PIX_FMT_H264) ++ size += CODA9_PS_SAVE_SIZE; ++ ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size, ++ "workbuf"); ++ if (ret < 0) ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ coda_free_context_buffers(ctx); ++ return ret; ++} ++ ++static int coda_encode_header(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, ++ int header_code, u8 *header, int *size) ++{ ++ struct vb2_buffer *vb = &buf->vb2_buf; ++ struct coda_dev *dev = ctx->dev; ++ struct coda_q_data *q_data_src; ++ struct v4l2_rect *r; ++ size_t bufsize; ++ int ret; ++ int i; ++ ++ if (dev->devtype->product == CODA_960) ++ memset(vb2_plane_vaddr(vb, 0), 0, 64); ++ ++ coda_write(dev, vb2_dma_contig_plane_dma_addr(vb, 0), ++ CODA_CMD_ENC_HEADER_BB_START); ++ bufsize = vb2_plane_size(vb, 0); ++ if (dev->devtype->product == CODA_960) ++ bufsize /= 1024; ++ coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE); ++ if (dev->devtype->product == CODA_960 && ++ ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 && ++ header_code == CODA_HEADER_H264_SPS) { ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ r = &q_data_src->rect; ++ ++ if (r->width % 16 || r->height % 16) { ++ u32 crop_right = round_up(r->width, 16) - r->width; ++ u32 crop_bottom = round_up(r->height, 16) - r->height; ++ ++ coda_write(dev, crop_right, ++ CODA9_CMD_ENC_HEADER_FRAME_CROP_H); ++ coda_write(dev, crop_bottom, ++ CODA9_CMD_ENC_HEADER_FRAME_CROP_V); ++ header_code |= CODA9_HEADER_FRAME_CROP; ++ } ++ } ++ coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE); ++ ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER); ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); ++ return ret; ++ } ++ ++ if (dev->devtype->product == CODA_960) { ++ for (i = 63; i > 0; i--) ++ if (((char *)vb2_plane_vaddr(vb, 0))[i] != 0) ++ break; ++ *size = i + 1; ++ } else { ++ *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - ++ coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); ++ } ++ memcpy(header, vb2_plane_vaddr(vb, 0), *size); ++ ++ return 0; ++} ++ ++static u32 coda_slice_mode(struct coda_ctx *ctx) ++{ ++ int size, unit; ++ ++ switch (ctx->params.slice_mode) { ++ case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: ++ default: ++ return 0; ++ case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB: ++ size = ctx->params.slice_max_mb; ++ unit = 1; ++ break; ++ case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES: ++ size = ctx->params.slice_max_bits; ++ unit = 0; ++ break; ++ } ++ ++ return ((size & CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET) | ++ ((unit & CODA_SLICING_UNIT_MASK) << CODA_SLICING_UNIT_OFFSET) | ++ ((1 & CODA_SLICING_MODE_MASK) << CODA_SLICING_MODE_OFFSET); ++} ++ ++static int coda_enc_param_change(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ u32 change_enable = 0; ++ u32 success; ++ int ret; ++ ++ if (ctx->params.gop_size_changed) { ++ change_enable |= CODA_PARAM_CHANGE_RC_GOP; ++ coda_write(dev, ctx->params.gop_size, ++ CODA_CMD_ENC_PARAM_RC_GOP); ++ ctx->gopcounter = ctx->params.gop_size - 1; ++ ctx->params.gop_size_changed = false; ++ } ++ if (ctx->params.h264_intra_qp_changed) { ++ coda_dbg(1, ctx, "parameter change: intra Qp %u\n", ++ ctx->params.h264_intra_qp); ++ ++ if (ctx->params.bitrate) { ++ change_enable |= CODA_PARAM_CHANGE_RC_INTRA_QP; ++ coda_write(dev, ctx->params.h264_intra_qp, ++ CODA_CMD_ENC_PARAM_RC_INTRA_QP); ++ } ++ ctx->params.h264_intra_qp_changed = false; ++ } ++ if (ctx->params.bitrate_changed) { ++ coda_dbg(1, ctx, "parameter change: bitrate %u kbit/s\n", ++ ctx->params.bitrate); ++ change_enable |= CODA_PARAM_CHANGE_RC_BITRATE; ++ coda_write(dev, ctx->params.bitrate, ++ CODA_CMD_ENC_PARAM_RC_BITRATE); ++ ctx->params.bitrate_changed = false; ++ } ++ if (ctx->params.framerate_changed) { ++ coda_dbg(1, ctx, "parameter change: frame rate %u/%u Hz\n", ++ ctx->params.framerate & 0xffff, ++ (ctx->params.framerate >> 16) + 1); ++ change_enable |= CODA_PARAM_CHANGE_RC_FRAME_RATE; ++ coda_write(dev, ctx->params.framerate, ++ CODA_CMD_ENC_PARAM_RC_FRAME_RATE); ++ ctx->params.framerate_changed = false; ++ } ++ if (ctx->params.intra_refresh_changed) { ++ coda_dbg(1, ctx, "parameter change: intra refresh MBs %u\n", ++ ctx->params.intra_refresh); ++ change_enable |= CODA_PARAM_CHANGE_INTRA_MB_NUM; ++ coda_write(dev, ctx->params.intra_refresh, ++ CODA_CMD_ENC_PARAM_INTRA_MB_NUM); ++ ctx->params.intra_refresh_changed = false; ++ } ++ if (ctx->params.slice_mode_changed) { ++ change_enable |= CODA_PARAM_CHANGE_SLICE_MODE; ++ coda_write(dev, coda_slice_mode(ctx), ++ CODA_CMD_ENC_PARAM_SLICE_MODE); ++ ctx->params.slice_mode_changed = false; ++ } ++ ++ if (!change_enable) ++ return 0; ++ ++ coda_write(dev, change_enable, CODA_CMD_ENC_PARAM_CHANGE_ENABLE); ++ ++ ret = coda_command_sync(ctx, CODA_COMMAND_RC_CHANGE_PARAMETER); ++ if (ret < 0) ++ return ret; ++ ++ success = coda_read(dev, CODA_RET_ENC_PARAM_CHANGE_SUCCESS); ++ if (success != 1) ++ coda_dbg(1, ctx, "parameter change failed: %u\n", success); ++ ++ return 0; ++} ++ ++static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size) ++{ ++ phys_addr_t ret; ++ ++ size = round_up(size, 1024); ++ if (size > iram->remaining) ++ return 0; ++ iram->remaining -= size; ++ ++ ret = iram->next_paddr; ++ iram->next_paddr += size; ++ ++ return ret; ++} ++ ++static void coda_setup_iram(struct coda_ctx *ctx) ++{ ++ struct coda_iram_info *iram_info = &ctx->iram_info; ++ struct coda_dev *dev = ctx->dev; ++ int w64, w128; ++ int mb_width; ++ int dbk_bits; ++ int bit_bits; ++ int ip_bits; ++ int me_bits; ++ ++ memset(iram_info, 0, sizeof(*iram_info)); ++ iram_info->next_paddr = dev->iram.paddr; ++ iram_info->remaining = dev->iram.size; ++ ++ if (!dev->iram.vaddr) ++ return; ++ ++ switch (dev->devtype->product) { ++ case CODA_HX4: ++ dbk_bits = CODA7_USE_HOST_DBK_ENABLE; ++ bit_bits = CODA7_USE_HOST_BIT_ENABLE; ++ ip_bits = CODA7_USE_HOST_IP_ENABLE; ++ me_bits = CODA7_USE_HOST_ME_ENABLE; ++ break; ++ case CODA_7541: ++ dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE; ++ bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE; ++ ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; ++ me_bits = CODA7_USE_HOST_ME_ENABLE | CODA7_USE_ME_ENABLE; ++ break; ++ case CODA_960: ++ dbk_bits = CODA9_USE_HOST_DBK_ENABLE | CODA9_USE_DBK_ENABLE; ++ bit_bits = CODA9_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE; ++ ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; ++ me_bits = 0; ++ break; ++ default: /* CODA_DX6 */ ++ return; ++ } ++ ++ if (ctx->inst_type == CODA_INST_ENCODER) { ++ struct coda_q_data *q_data_src; ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ mb_width = DIV_ROUND_UP(q_data_src->rect.width, 16); ++ w128 = mb_width * 128; ++ w64 = mb_width * 64; ++ ++ /* Prioritize in case IRAM is too small for everything */ ++ if (dev->devtype->product == CODA_HX4 || ++ dev->devtype->product == CODA_7541) { ++ iram_info->search_ram_size = round_up(mb_width * 16 * ++ 36 + 2048, 1024); ++ iram_info->search_ram_paddr = coda_iram_alloc(iram_info, ++ iram_info->search_ram_size); ++ if (!iram_info->search_ram_paddr) { ++ pr_err("IRAM is smaller than the search ram size\n"); ++ goto out; ++ } ++ iram_info->axi_sram_use |= me_bits; ++ } ++ ++ /* Only H.264BP and H.263P3 are considered */ ++ iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64); ++ iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64); ++ if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) ++ goto out; ++ iram_info->axi_sram_use |= dbk_bits; ++ ++ iram_info->buf_bit_use = coda_iram_alloc(iram_info, w128); ++ if (!iram_info->buf_bit_use) ++ goto out; ++ iram_info->axi_sram_use |= bit_bits; ++ ++ iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, w128); ++ if (!iram_info->buf_ip_ac_dc_use) ++ goto out; ++ iram_info->axi_sram_use |= ip_bits; ++ ++ /* OVL and BTP disabled for encoder */ ++ } else if (ctx->inst_type == CODA_INST_DECODER) { ++ struct coda_q_data *q_data_dst; ++ ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ mb_width = DIV_ROUND_UP(q_data_dst->width, 16); ++ w128 = mb_width * 128; ++ ++ iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w128); ++ iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w128); ++ if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) ++ goto out; ++ iram_info->axi_sram_use |= dbk_bits; ++ ++ iram_info->buf_bit_use = coda_iram_alloc(iram_info, w128); ++ if (!iram_info->buf_bit_use) ++ goto out; ++ iram_info->axi_sram_use |= bit_bits; ++ ++ iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, w128); ++ if (!iram_info->buf_ip_ac_dc_use) ++ goto out; ++ iram_info->axi_sram_use |= ip_bits; ++ ++ /* OVL and BTP unused as there is no VC1 support yet */ ++ } ++ ++out: ++ if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)) ++ coda_dbg(1, ctx, "IRAM smaller than needed\n"); ++ ++ if (dev->devtype->product == CODA_HX4 || ++ dev->devtype->product == CODA_7541) { ++ /* TODO - Enabling these causes picture errors on CODA7541 */ ++ if (ctx->inst_type == CODA_INST_DECODER) { ++ /* fw 1.4.50 */ ++ iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE | ++ CODA7_USE_IP_ENABLE); ++ } else { ++ /* fw 13.4.29 */ ++ iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE | ++ CODA7_USE_HOST_DBK_ENABLE | ++ CODA7_USE_IP_ENABLE | ++ CODA7_USE_DBK_ENABLE); ++ } ++ } ++} ++ ++static u32 coda_supported_firmwares[] = { ++ CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), ++ CODA_FIRMWARE_VERNUM(CODA_HX4, 1, 4, 50), ++ CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50), ++ CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5), ++ CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 9), ++ CODA_FIRMWARE_VERNUM(CODA_960, 2, 3, 10), ++ CODA_FIRMWARE_VERNUM(CODA_960, 3, 1, 1), ++}; ++ ++static bool coda_firmware_supported(u32 vernum) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++) ++ if (vernum == coda_supported_firmwares[i]) ++ return true; ++ return false; ++} ++ ++int coda_check_firmware(struct coda_dev *dev) ++{ ++ u16 product, major, minor, release; ++ u32 data; ++ int ret; ++ ++ ret = clk_prepare_enable(dev->clk_per); ++ if (ret) ++ goto err_clk_per; ++ ++ ret = clk_prepare_enable(dev->clk_ahb); ++ if (ret) ++ goto err_clk_ahb; ++ ++ coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM); ++ coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); ++ coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX); ++ coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD); ++ coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND); ++ if (coda_wait_timeout(dev)) { ++ v4l2_err(&dev->v4l2_dev, "firmware get command error\n"); ++ ret = -EIO; ++ goto err_run_cmd; ++ } ++ ++ if (dev->devtype->product == CODA_960) { ++ data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV); ++ v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n", ++ data); ++ } ++ ++ /* Check we are compatible with the loaded firmware */ ++ data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM); ++ product = CODA_FIRMWARE_PRODUCT(data); ++ major = CODA_FIRMWARE_MAJOR(data); ++ minor = CODA_FIRMWARE_MINOR(data); ++ release = CODA_FIRMWARE_RELEASE(data); ++ ++ clk_disable_unprepare(dev->clk_per); ++ clk_disable_unprepare(dev->clk_ahb); ++ ++ if (product != dev->devtype->product) { ++ v4l2_err(&dev->v4l2_dev, ++ "Wrong firmware. Hw: %s, Fw: %s, Version: %u.%u.%u\n", ++ coda_product_name(dev->devtype->product), ++ coda_product_name(product), major, minor, release); ++ return -EINVAL; ++ } ++ ++ v4l2_info(&dev->v4l2_dev, "Initialized %s.\n", ++ coda_product_name(product)); ++ ++ if (coda_firmware_supported(data)) { ++ v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n", ++ major, minor, release); ++ } else { ++ v4l2_warn(&dev->v4l2_dev, ++ "Unsupported firmware version: %u.%u.%u\n", ++ major, minor, release); ++ } ++ ++ return 0; ++ ++err_run_cmd: ++ clk_disable_unprepare(dev->clk_ahb); ++err_clk_ahb: ++ clk_disable_unprepare(dev->clk_per); ++err_clk_per: ++ return ret; ++} ++ ++static void coda9_set_frame_cache(struct coda_ctx *ctx, u32 fourcc) ++{ ++ u32 cache_size, cache_config; ++ ++ if (ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) { ++ /* Luma 2x0 page, 2x6 cache, chroma 2x0 page, 2x4 cache size */ ++ cache_size = 0x20262024; ++ cache_config = 2 << CODA9_CACHE_PAGEMERGE_OFFSET; ++ } else { ++ /* Luma 0x2 page, 4x4 cache, chroma 0x2 page, 4x3 cache size */ ++ cache_size = 0x02440243; ++ cache_config = 1 << CODA9_CACHE_PAGEMERGE_OFFSET; ++ } ++ coda_write(ctx->dev, cache_size, CODA9_CMD_SET_FRAME_CACHE_SIZE); ++ if (fourcc == V4L2_PIX_FMT_NV12 || fourcc == V4L2_PIX_FMT_YUYV) { ++ cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | ++ 16 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET | ++ 0 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET; ++ } else { ++ cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | ++ 8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET | ++ 8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET; ++ } ++ coda_write(ctx->dev, cache_config, CODA9_CMD_SET_FRAME_CACHE_CONFIG); ++} ++ ++/* ++ * Encoder context operations ++ */ ++ ++static int coda_encoder_reqbufs(struct coda_ctx *ctx, ++ struct v4l2_requestbuffers *rb) ++{ ++ struct coda_q_data *q_data_src; ++ int ret; ++ ++ if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return 0; ++ ++ if (rb->count) { ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ ret = coda_alloc_context_buffers(ctx, q_data_src); ++ if (ret < 0) ++ return ret; ++ } else { ++ coda_free_context_buffers(ctx); ++ } ++ ++ return 0; ++} ++ ++static int coda_start_encoding(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ struct v4l2_device *v4l2_dev = &dev->v4l2_dev; ++ struct coda_q_data *q_data_src, *q_data_dst; ++ u32 bitstream_buf, bitstream_size; ++ struct vb2_v4l2_buffer *buf; ++ int gamma, ret, value; ++ u32 dst_fourcc; ++ int num_fb; ++ u32 stride; ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ dst_fourcc = q_data_dst->fourcc; ++ ++ buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ++ bitstream_buf = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0); ++ bitstream_size = q_data_dst->sizeimage; ++ ++ if (!coda_is_initialized(dev)) { ++ v4l2_err(v4l2_dev, "coda is not initialized.\n"); ++ return -EFAULT; ++ } ++ ++ if (dst_fourcc == V4L2_PIX_FMT_JPEG) { ++ if (!ctx->params.jpeg_qmat_tab[0]) { ++ ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[0]) ++ return -ENOMEM; ++ } ++ if (!ctx->params.jpeg_qmat_tab[1]) { ++ ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[1]) ++ return -ENOMEM; ++ } ++ coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); ++ } ++ ++ mutex_lock(&dev->coda_mutex); ++ ++ coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); ++ coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); ++ coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); ++ switch (dev->devtype->product) { ++ case CODA_DX6: ++ coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | ++ CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); ++ break; ++ case CODA_960: ++ coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); ++ fallthrough; ++ case CODA_HX4: ++ case CODA_7541: ++ coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN | ++ CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); ++ break; ++ } ++ ++ ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) | ++ CODA9_FRAME_TILED2LINEAR); ++ if (q_data_src->fourcc == V4L2_PIX_FMT_NV12) ++ ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE; ++ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) ++ ctx->frame_mem_ctrl |= (0x3 << 9) | CODA9_FRAME_TILED2LINEAR; ++ coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL); ++ ++ if (dev->devtype->product == CODA_DX6) { ++ /* Configure the coda */ ++ coda_write(dev, dev->iram.paddr, ++ CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR); ++ } ++ ++ /* Could set rotation here if needed */ ++ value = 0; ++ switch (dev->devtype->product) { ++ case CODA_DX6: ++ value = (q_data_src->rect.width & CODADX6_PICWIDTH_MASK) ++ << CODADX6_PICWIDTH_OFFSET; ++ value |= (q_data_src->rect.height & CODADX6_PICHEIGHT_MASK) ++ << CODA_PICHEIGHT_OFFSET; ++ break; ++ case CODA_HX4: ++ case CODA_7541: ++ if (dst_fourcc == V4L2_PIX_FMT_H264) { ++ value = (round_up(q_data_src->rect.width, 16) & ++ CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; ++ value |= (round_up(q_data_src->rect.height, 16) & ++ CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; ++ break; ++ } ++ fallthrough; ++ case CODA_960: ++ value = (q_data_src->rect.width & CODA7_PICWIDTH_MASK) ++ << CODA7_PICWIDTH_OFFSET; ++ value |= (q_data_src->rect.height & CODA7_PICHEIGHT_MASK) ++ << CODA_PICHEIGHT_OFFSET; ++ } ++ coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE); ++ if (dst_fourcc == V4L2_PIX_FMT_JPEG) ++ ctx->params.framerate = 0; ++ coda_write(dev, ctx->params.framerate, ++ CODA_CMD_ENC_SEQ_SRC_F_RATE); ++ ++ ctx->params.codec_mode = ctx->codec->mode; ++ switch (dst_fourcc) { ++ case V4L2_PIX_FMT_MPEG4: ++ if (dev->devtype->product == CODA_960) ++ coda_write(dev, CODA9_STD_MPEG4, ++ CODA_CMD_ENC_SEQ_COD_STD); ++ else ++ coda_write(dev, CODA_STD_MPEG4, ++ CODA_CMD_ENC_SEQ_COD_STD); ++ coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); ++ break; ++ case V4L2_PIX_FMT_H264: ++ if (dev->devtype->product == CODA_960) ++ coda_write(dev, CODA9_STD_H264, ++ CODA_CMD_ENC_SEQ_COD_STD); ++ else ++ coda_write(dev, CODA_STD_H264, ++ CODA_CMD_ENC_SEQ_COD_STD); ++ value = ((ctx->params.h264_disable_deblocking_filter_idc & ++ CODA_264PARAM_DISABLEDEBLK_MASK) << ++ CODA_264PARAM_DISABLEDEBLK_OFFSET) | ++ ((ctx->params.h264_slice_alpha_c0_offset_div2 & ++ CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) << ++ CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) | ++ ((ctx->params.h264_slice_beta_offset_div2 & ++ CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) << ++ CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET) | ++ (ctx->params.h264_constrained_intra_pred_flag << ++ CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET) | ++ (ctx->params.h264_chroma_qp_index_offset & ++ CODA_264PARAM_CHROMAQPOFFSET_MASK); ++ coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA); ++ break; ++ case V4L2_PIX_FMT_JPEG: ++ coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_PARA); ++ coda_write(dev, ctx->params.jpeg_restart_interval, ++ CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL); ++ coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_EN); ++ coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE); ++ coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET); ++ ++ coda_jpeg_write_tables(ctx); ++ break; ++ default: ++ v4l2_err(v4l2_dev, ++ "dst format (0x%08x) invalid.\n", dst_fourcc); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* ++ * slice mode and GOP size registers are used for thumb size/offset ++ * in JPEG mode ++ */ ++ if (dst_fourcc != V4L2_PIX_FMT_JPEG) { ++ value = coda_slice_mode(ctx); ++ coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE); ++ value = ctx->params.gop_size; ++ coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE); ++ } ++ ++ if (ctx->params.bitrate && (ctx->params.frame_rc_enable || ++ ctx->params.mb_rc_enable)) { ++ ctx->params.bitrate_changed = false; ++ ctx->params.h264_intra_qp_changed = false; ++ ++ /* Rate control enabled */ ++ value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK) ++ << CODA_RATECONTROL_BITRATE_OFFSET; ++ value |= 1 & CODA_RATECONTROL_ENABLE_MASK; ++ value |= (ctx->params.vbv_delay & ++ CODA_RATECONTROL_INITIALDELAY_MASK) ++ << CODA_RATECONTROL_INITIALDELAY_OFFSET; ++ if (dev->devtype->product == CODA_960) ++ value |= BIT(31); /* disable autoskip */ ++ } else { ++ value = 0; ++ } ++ coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA); ++ ++ coda_write(dev, ctx->params.vbv_size, CODA_CMD_ENC_SEQ_RC_BUF_SIZE); ++ coda_write(dev, ctx->params.intra_refresh, ++ CODA_CMD_ENC_SEQ_INTRA_REFRESH); ++ ++ coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START); ++ coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE); ++ ++ ++ value = 0; ++ if (dev->devtype->product == CODA_960) ++ gamma = CODA9_DEFAULT_GAMMA; ++ else ++ gamma = CODA_DEFAULT_GAMMA; ++ if (gamma > 0) { ++ coda_write(dev, (gamma & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET, ++ CODA_CMD_ENC_SEQ_RC_GAMMA); ++ } ++ ++ if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) { ++ coda_write(dev, ++ ctx->params.h264_min_qp << CODA_QPMIN_OFFSET | ++ ctx->params.h264_max_qp << CODA_QPMAX_OFFSET, ++ CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX); ++ } ++ if (dev->devtype->product == CODA_960) { ++ if (ctx->params.h264_max_qp) ++ value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET; ++ if (CODA_DEFAULT_GAMMA > 0) ++ value |= 1 << CODA9_OPTION_GAMMA_OFFSET; ++ } else { ++ if (CODA_DEFAULT_GAMMA > 0) { ++ if (dev->devtype->product == CODA_DX6) ++ value |= 1 << CODADX6_OPTION_GAMMA_OFFSET; ++ else ++ value |= 1 << CODA7_OPTION_GAMMA_OFFSET; ++ } ++ if (ctx->params.h264_min_qp) ++ value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET; ++ if (ctx->params.h264_max_qp) ++ value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET; ++ } ++ coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); ++ ++ if (ctx->params.frame_rc_enable && !ctx->params.mb_rc_enable) ++ value = 1; ++ else ++ value = 0; ++ coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE); ++ ++ coda_setup_iram(ctx); ++ ++ if (dst_fourcc == V4L2_PIX_FMT_H264) { ++ switch (dev->devtype->product) { ++ case CODA_DX6: ++ value = FMO_SLICE_SAVE_BUF_SIZE << 7; ++ coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); ++ break; ++ case CODA_HX4: ++ case CODA_7541: ++ coda_write(dev, ctx->iram_info.search_ram_paddr, ++ CODA7_CMD_ENC_SEQ_SEARCH_BASE); ++ coda_write(dev, ctx->iram_info.search_ram_size, ++ CODA7_CMD_ENC_SEQ_SEARCH_SIZE); ++ break; ++ case CODA_960: ++ coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION); ++ coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT); ++ } ++ } ++ ++ ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT); ++ if (ret < 0) { ++ v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); ++ goto out; ++ } ++ ++ if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) { ++ v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n"); ++ ret = -EFAULT; ++ goto out; ++ } ++ ctx->initialized = 1; ++ ++ if (dst_fourcc != V4L2_PIX_FMT_JPEG) { ++ if (dev->devtype->product == CODA_960) ++ ctx->num_internal_frames = 4; ++ else ++ ctx->num_internal_frames = 2; ++ ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); ++ if (ret < 0) { ++ v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); ++ goto out; ++ } ++ num_fb = 2; ++ stride = q_data_src->bytesperline; ++ } else { ++ ctx->num_internal_frames = 0; ++ num_fb = 0; ++ stride = 0; ++ } ++ coda_write(dev, num_fb, CODA_CMD_SET_FRAME_BUF_NUM); ++ coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE); ++ ++ if (dev->devtype->product == CODA_HX4 || ++ dev->devtype->product == CODA_7541) { ++ coda_write(dev, q_data_src->bytesperline, ++ CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); ++ } ++ if (dev->devtype->product != CODA_DX6) { ++ coda_write(dev, ctx->iram_info.buf_bit_use, ++ CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); ++ coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, ++ CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); ++ coda_write(dev, ctx->iram_info.buf_dbk_y_use, ++ CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); ++ coda_write(dev, ctx->iram_info.buf_dbk_c_use, ++ CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); ++ coda_write(dev, ctx->iram_info.buf_ovl_use, ++ CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); ++ if (dev->devtype->product == CODA_960) { ++ coda_write(dev, ctx->iram_info.buf_btp_use, ++ CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); ++ ++ coda9_set_frame_cache(ctx, q_data_src->fourcc); ++ ++ /* FIXME */ ++ coda_write(dev, ctx->internal_frames[2].buf.paddr, ++ CODA9_CMD_SET_FRAME_SUBSAMP_A); ++ coda_write(dev, ctx->internal_frames[3].buf.paddr, ++ CODA9_CMD_SET_FRAME_SUBSAMP_B); ++ } ++ } ++ ++ ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); ++ if (ret < 0) { ++ v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); ++ goto out; ++ } ++ ++ coda_dbg(1, ctx, "start encoding %dx%d %4.4s->%4.4s @ %d/%d Hz\n", ++ q_data_src->rect.width, q_data_src->rect.height, ++ (char *)&ctx->codec->src_fourcc, (char *)&dst_fourcc, ++ ctx->params.framerate & 0xffff, ++ (ctx->params.framerate >> 16) + 1); ++ ++ /* Save stream headers */ ++ buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ++ switch (dst_fourcc) { ++ case V4L2_PIX_FMT_H264: ++ /* ++ * Get SPS in the first frame and copy it to an ++ * intermediate buffer. ++ */ ++ ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS, ++ &ctx->vpu_header[0][0], ++ &ctx->vpu_header_size[0]); ++ if (ret < 0) ++ goto out; ++ ++ /* ++ * If visible width or height are not aligned to macroblock ++ * size, the crop_right and crop_bottom SPS fields must be set ++ * to the difference between visible and coded size. This is ++ * only supported by CODA960 firmware. All others do not allow ++ * writing frame cropping parameters, so we have to manually ++ * fix up the SPS RBSP (Sequence Parameter Set Raw Byte ++ * Sequence Payload) ourselves. ++ */ ++ if (ctx->dev->devtype->product != CODA_960 && ++ ((q_data_src->rect.width % 16) || ++ (q_data_src->rect.height % 16))) { ++ ret = coda_h264_sps_fixup(ctx, q_data_src->rect.width, ++ q_data_src->rect.height, ++ &ctx->vpu_header[0][0], ++ &ctx->vpu_header_size[0], ++ sizeof(ctx->vpu_header[0])); ++ if (ret < 0) ++ goto out; ++ } ++ ++ /* ++ * Get PPS in the first frame and copy it to an ++ * intermediate buffer. ++ */ ++ ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS, ++ &ctx->vpu_header[1][0], ++ &ctx->vpu_header_size[1]); ++ if (ret < 0) ++ goto out; ++ ++ /* ++ * Length of H.264 headers is variable and thus it might not be ++ * aligned for the coda to append the encoded frame. In that is ++ * the case a filler NAL must be added to header 2. ++ */ ++ ctx->vpu_header_size[2] = coda_h264_padding( ++ (ctx->vpu_header_size[0] + ++ ctx->vpu_header_size[1]), ++ ctx->vpu_header[2]); ++ break; ++ case V4L2_PIX_FMT_MPEG4: ++ /* ++ * Get VOS in the first frame and copy it to an ++ * intermediate buffer ++ */ ++ ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS, ++ &ctx->vpu_header[0][0], ++ &ctx->vpu_header_size[0]); ++ if (ret < 0) ++ goto out; ++ ++ ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS, ++ &ctx->vpu_header[1][0], ++ &ctx->vpu_header_size[1]); ++ if (ret < 0) ++ goto out; ++ ++ ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL, ++ &ctx->vpu_header[2][0], ++ &ctx->vpu_header_size[2]); ++ if (ret < 0) ++ goto out; ++ break; ++ default: ++ /* No more formats need to save headers at the moment */ ++ break; ++ } ++ ++out: ++ mutex_unlock(&dev->coda_mutex); ++ return ret; ++} ++ ++static int coda_prepare_encode(struct coda_ctx *ctx) ++{ ++ struct coda_q_data *q_data_src, *q_data_dst; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ struct coda_dev *dev = ctx->dev; ++ int force_ipicture; ++ int quant_param = 0; ++ u32 pic_stream_buffer_addr, pic_stream_buffer_size; ++ u32 rot_mode = 0; ++ u32 dst_fourcc; ++ u32 reg; ++ int ret; ++ ++ ret = coda_enc_param_change(ctx); ++ if (ret < 0) { ++ v4l2_warn(&ctx->dev->v4l2_dev, "parameter change failed: %d\n", ++ ret); ++ } ++ ++ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ dst_fourcc = q_data_dst->fourcc; ++ ++ src_buf->sequence = ctx->osequence; ++ dst_buf->sequence = ctx->osequence; ++ ctx->osequence++; ++ ++ force_ipicture = ctx->params.force_ipicture; ++ if (force_ipicture) ++ ctx->params.force_ipicture = false; ++ else if (ctx->params.gop_size != 0 && ++ (src_buf->sequence % ctx->params.gop_size) == 0) ++ force_ipicture = 1; ++ ++ /* ++ * Workaround coda firmware BUG that only marks the first ++ * frame as IDR. This is a problem for some decoders that can't ++ * recover when a frame is lost. ++ */ ++ if (!force_ipicture) { ++ src_buf->flags |= V4L2_BUF_FLAG_PFRAME; ++ src_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME; ++ } else { ++ src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; ++ src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME; ++ } ++ ++ if (dev->devtype->product == CODA_960) ++ coda_set_gdi_regs(ctx); ++ ++ /* ++ * Copy headers in front of the first frame and forced I frames for ++ * H.264 only. In MPEG4 they are already copied by the CODA. ++ */ ++ if (src_buf->sequence == 0 || force_ipicture) { ++ pic_stream_buffer_addr = ++ vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0) + ++ ctx->vpu_header_size[0] + ++ ctx->vpu_header_size[1] + ++ ctx->vpu_header_size[2]; ++ pic_stream_buffer_size = q_data_dst->sizeimage - ++ ctx->vpu_header_size[0] - ++ ctx->vpu_header_size[1] - ++ ctx->vpu_header_size[2]; ++ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0), ++ &ctx->vpu_header[0][0], ctx->vpu_header_size[0]); ++ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) ++ + ctx->vpu_header_size[0], &ctx->vpu_header[1][0], ++ ctx->vpu_header_size[1]); ++ memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) ++ + ctx->vpu_header_size[0] + ctx->vpu_header_size[1], ++ &ctx->vpu_header[2][0], ctx->vpu_header_size[2]); ++ } else { ++ pic_stream_buffer_addr = ++ vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); ++ pic_stream_buffer_size = q_data_dst->sizeimage; ++ } ++ ++ if (force_ipicture) { ++ switch (dst_fourcc) { ++ case V4L2_PIX_FMT_H264: ++ quant_param = ctx->params.h264_intra_qp; ++ break; ++ case V4L2_PIX_FMT_MPEG4: ++ quant_param = ctx->params.mpeg4_intra_qp; ++ break; ++ case V4L2_PIX_FMT_JPEG: ++ quant_param = 30; ++ break; ++ default: ++ v4l2_warn(&ctx->dev->v4l2_dev, ++ "cannot set intra qp, fmt not supported\n"); ++ break; ++ } ++ } else { ++ switch (dst_fourcc) { ++ case V4L2_PIX_FMT_H264: ++ quant_param = ctx->params.h264_inter_qp; ++ break; ++ case V4L2_PIX_FMT_MPEG4: ++ quant_param = ctx->params.mpeg4_inter_qp; ++ break; ++ default: ++ v4l2_warn(&ctx->dev->v4l2_dev, ++ "cannot set inter qp, fmt not supported\n"); ++ break; ++ } ++ } ++ ++ /* submit */ ++ if (ctx->params.rot_mode) ++ rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode; ++ coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE); ++ coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS); ++ ++ if (dev->devtype->product == CODA_960) { ++ coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX); ++ coda_write(dev, q_data_src->bytesperline, ++ CODA9_CMD_ENC_PIC_SRC_STRIDE); ++ coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC); ++ ++ reg = CODA9_CMD_ENC_PIC_SRC_ADDR_Y; ++ } else { ++ reg = CODA_CMD_ENC_PIC_SRC_ADDR_Y; ++ } ++ coda_write_base(ctx, q_data_src, src_buf, reg); ++ ++ coda_write(dev, force_ipicture << 1 & 0x2, ++ CODA_CMD_ENC_PIC_OPTION); ++ ++ coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); ++ coda_write(dev, pic_stream_buffer_size / 1024, ++ CODA_CMD_ENC_PIC_BB_SIZE); ++ ++ if (!ctx->streamon_out) { ++ /* After streamoff on the output side, set stream end flag */ ++ ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; ++ coda_write(dev, ctx->bit_stream_param, ++ CODA_REG_BIT_BIT_STREAM_PARAM); ++ } ++ ++ if (dev->devtype->product != CODA_DX6) ++ coda_write(dev, ctx->iram_info.axi_sram_use, ++ CODA7_REG_BIT_AXI_SRAM_USE); ++ ++ trace_coda_enc_pic_run(ctx, src_buf); ++ ++ coda_command_async(ctx, CODA_COMMAND_PIC_RUN); ++ ++ return 0; ++} ++ ++static char coda_frame_type_char(u32 flags) ++{ ++ return (flags & V4L2_BUF_FLAG_KEYFRAME) ? 'I' : ++ (flags & V4L2_BUF_FLAG_PFRAME) ? 'P' : ++ (flags & V4L2_BUF_FLAG_BFRAME) ? 'B' : '?'; ++} ++ ++static void coda_finish_encode(struct coda_ctx *ctx) ++{ ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ struct coda_dev *dev = ctx->dev; ++ u32 wr_ptr, start_ptr; ++ ++ if (ctx->aborting) ++ return; ++ ++ /* ++ * Lock to make sure that an encoder stop command running in parallel ++ * will either already have marked src_buf as last, or it will wake up ++ * the capture queue after the buffers are returned. ++ */ ++ mutex_lock(&ctx->wakeup_mutex); ++ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ++ ++ trace_coda_enc_pic_done(ctx, dst_buf); ++ ++ /* Get results from the coda */ ++ start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); ++ wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); ++ ++ /* Calculate bytesused field */ ++ if (dst_buf->sequence == 0 || ++ src_buf->flags & V4L2_BUF_FLAG_KEYFRAME) { ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr + ++ ctx->vpu_header_size[0] + ++ ctx->vpu_header_size[1] + ++ ctx->vpu_header_size[2]); ++ } else { ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr); ++ } ++ ++ coda_dbg(1, ctx, "frame size = %u\n", wr_ptr - start_ptr); ++ ++ coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM); ++ coda_read(dev, CODA_RET_ENC_PIC_FLAG); ++ ++ dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | ++ V4L2_BUF_FLAG_PFRAME | ++ V4L2_BUF_FLAG_LAST); ++ if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) ++ dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; ++ else ++ dst_buf->flags |= V4L2_BUF_FLAG_PFRAME; ++ dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST; ++ ++ v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); ++ ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ ++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); ++ coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE); ++ mutex_unlock(&ctx->wakeup_mutex); ++ ++ ctx->gopcounter--; ++ if (ctx->gopcounter < 0) ++ ctx->gopcounter = ctx->params.gop_size - 1; ++ ++ coda_dbg(1, ctx, "job finished: encoded %c frame (%d)%s\n", ++ coda_frame_type_char(dst_buf->flags), dst_buf->sequence, ++ (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : ""); ++} ++ ++static void coda_seq_end_work(struct work_struct *work) ++{ ++ struct coda_ctx *ctx = container_of(work, struct coda_ctx, seq_end_work); ++ struct coda_dev *dev = ctx->dev; ++ ++ mutex_lock(&ctx->buffer_mutex); ++ mutex_lock(&dev->coda_mutex); ++ ++ if (ctx->initialized == 0) ++ goto out; ++ ++ coda_dbg(1, ctx, "%s: sent command 'SEQ_END' to coda\n", __func__); ++ if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { ++ v4l2_err(&dev->v4l2_dev, ++ "CODA_COMMAND_SEQ_END failed\n"); ++ } ++ ++ /* ++ * FIXME: Sometimes h.264 encoding fails with 8-byte sequences missing ++ * from the output stream after the h.264 decoder has run. Resetting the ++ * hardware after the decoder has finished seems to help. ++ */ ++ if (dev->devtype->product == CODA_960) ++ coda_hw_reset(ctx); ++ ++ kfifo_init(&ctx->bitstream_fifo, ++ ctx->bitstream.vaddr, ctx->bitstream.size); ++ ++ coda_free_framebuffers(ctx); ++ ++ ctx->initialized = 0; ++ ++out: ++ mutex_unlock(&dev->coda_mutex); ++ mutex_unlock(&ctx->buffer_mutex); ++} ++ ++static void coda_bit_release(struct coda_ctx *ctx) ++{ ++ mutex_lock(&ctx->buffer_mutex); ++ coda_free_framebuffers(ctx); ++ coda_free_context_buffers(ctx); ++ coda_free_bitstream_buffer(ctx); ++ mutex_unlock(&ctx->buffer_mutex); ++} ++ ++const struct coda_context_ops coda_bit_encode_ops = { ++ .queue_init = coda_encoder_queue_init, ++ .reqbufs = coda_encoder_reqbufs, ++ .start_streaming = coda_start_encoding, ++ .prepare_run = coda_prepare_encode, ++ .finish_run = coda_finish_encode, ++ .seq_end_work = coda_seq_end_work, ++ .release = coda_bit_release, ++}; ++ ++/* ++ * Decoder context operations ++ */ ++ ++static int coda_alloc_bitstream_buffer(struct coda_ctx *ctx, ++ struct coda_q_data *q_data) ++{ ++ if (ctx->bitstream.vaddr) ++ return 0; ++ ++ ctx->bitstream.size = roundup_pow_of_two(q_data->sizeimage * 2); ++ ctx->bitstream.vaddr = dma_alloc_wc(ctx->dev->dev, ctx->bitstream.size, ++ &ctx->bitstream.paddr, GFP_KERNEL); ++ if (!ctx->bitstream.vaddr) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "failed to allocate bitstream ringbuffer"); ++ return -ENOMEM; ++ } ++ kfifo_init(&ctx->bitstream_fifo, ++ ctx->bitstream.vaddr, ctx->bitstream.size); ++ ++ return 0; ++} ++ ++static void coda_free_bitstream_buffer(struct coda_ctx *ctx) ++{ ++ if (ctx->bitstream.vaddr == NULL) ++ return; ++ ++ dma_free_wc(ctx->dev->dev, ctx->bitstream.size, ctx->bitstream.vaddr, ++ ctx->bitstream.paddr); ++ ctx->bitstream.vaddr = NULL; ++ kfifo_init(&ctx->bitstream_fifo, NULL, 0); ++} ++ ++static int coda_decoder_reqbufs(struct coda_ctx *ctx, ++ struct v4l2_requestbuffers *rb) ++{ ++ struct coda_q_data *q_data_src; ++ int ret; ++ ++ if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return 0; ++ ++ if (rb->count) { ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ ret = coda_alloc_context_buffers(ctx, q_data_src); ++ if (ret < 0) ++ return ret; ++ ret = coda_alloc_bitstream_buffer(ctx, q_data_src); ++ if (ret < 0) { ++ coda_free_context_buffers(ctx); ++ return ret; ++ } ++ } else { ++ coda_free_bitstream_buffer(ctx); ++ coda_free_context_buffers(ctx); ++ } ++ ++ return 0; ++} ++ ++static bool coda_reorder_enable(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ int profile; ++ ++ if (dev->devtype->product != CODA_HX4 && ++ dev->devtype->product != CODA_7541 && ++ dev->devtype->product != CODA_960) ++ return false; ++ ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) ++ return false; ++ ++ if (ctx->codec->src_fourcc != V4L2_PIX_FMT_H264) ++ return true; ++ ++ profile = coda_h264_profile(ctx->params.h264_profile_idc); ++ if (profile < 0) ++ v4l2_warn(&dev->v4l2_dev, "Unknown H264 Profile: %u\n", ++ ctx->params.h264_profile_idc); ++ ++ /* Baseline profile does not support reordering */ ++ return profile > V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; ++} ++ ++static void coda_decoder_drop_used_metas(struct coda_ctx *ctx) ++{ ++ struct coda_buffer_meta *meta, *tmp; ++ ++ /* ++ * All metas that end at or before the RD pointer (fifo out), ++ * are now consumed by the VPU and should be released. ++ */ ++ spin_lock(&ctx->buffer_meta_lock); ++ list_for_each_entry_safe(meta, tmp, &ctx->buffer_meta_list, list) { ++ if (ctx->bitstream_fifo.kfifo.out >= meta->end) { ++ coda_dbg(2, ctx, "releasing meta: seq=%d start=%d end=%d\n", ++ meta->sequence, meta->start, meta->end); ++ ++ list_del(&meta->list); ++ ctx->num_metas--; ++ ctx->first_frame_sequence++; ++ kfree(meta); ++ } ++ } ++ spin_unlock(&ctx->buffer_meta_lock); ++} ++ ++static int __coda_decoder_seq_init(struct coda_ctx *ctx) ++{ ++ struct coda_q_data *q_data_src, *q_data_dst; ++ u32 bitstream_buf, bitstream_size; ++ struct coda_dev *dev = ctx->dev; ++ int width, height; ++ u32 src_fourcc, dst_fourcc; ++ u32 val; ++ int ret; ++ ++ lockdep_assert_held(&dev->coda_mutex); ++ ++ coda_dbg(1, ctx, "Video Data Order Adapter: %s\n", ++ ctx->use_vdoa ? "Enabled" : "Disabled"); ++ ++ /* Start decoding */ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ bitstream_buf = ctx->bitstream.paddr; ++ bitstream_size = ctx->bitstream.size; ++ src_fourcc = q_data_src->fourcc; ++ dst_fourcc = q_data_dst->fourcc; ++ ++ /* Update coda bitstream read and write pointers from kfifo */ ++ coda_kfifo_sync_to_device_full(ctx); ++ ++ ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) | ++ CODA9_FRAME_TILED2LINEAR); ++ if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV) ++ ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE; ++ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) ++ ctx->frame_mem_ctrl |= (0x3 << 9) | ++ ((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR); ++ coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL); ++ ++ ctx->display_idx = -1; ++ ctx->frm_dis_flg = 0; ++ coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); ++ ++ coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START); ++ coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE); ++ val = 0; ++ if (coda_reorder_enable(ctx)) ++ val |= CODA_REORDER_ENABLE; ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) ++ val |= CODA_NO_INT_ENABLE; ++ coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); ++ ++ ctx->params.codec_mode = ctx->codec->mode; ++ if (dev->devtype->product == CODA_960 && ++ src_fourcc == V4L2_PIX_FMT_MPEG4) ++ ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4; ++ else ++ ctx->params.codec_mode_aux = 0; ++ if (src_fourcc == V4L2_PIX_FMT_MPEG4) { ++ coda_write(dev, CODA_MP4_CLASS_MPEG4, ++ CODA_CMD_DEC_SEQ_MP4_ASP_CLASS); ++ } ++ if (src_fourcc == V4L2_PIX_FMT_H264) { ++ if (dev->devtype->product == CODA_HX4 || ++ dev->devtype->product == CODA_7541) { ++ coda_write(dev, ctx->psbuf.paddr, ++ CODA_CMD_DEC_SEQ_PS_BB_START); ++ coda_write(dev, (CODA7_PS_BUF_SIZE / 1024), ++ CODA_CMD_DEC_SEQ_PS_BB_SIZE); ++ } ++ if (dev->devtype->product == CODA_960) { ++ coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN); ++ coda_write(dev, 512, CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE); ++ } ++ } ++ if (src_fourcc == V4L2_PIX_FMT_JPEG) ++ coda_write(dev, 0, CODA_CMD_DEC_SEQ_JPG_THUMB_EN); ++ if (dev->devtype->product != CODA_960) ++ coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE); ++ ++ ctx->bit_stream_param = CODA_BIT_DEC_SEQ_INIT_ESCAPE; ++ ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT); ++ ctx->bit_stream_param = 0; ++ if (ret) { ++ v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); ++ return ret; ++ } ++ ctx->sequence_offset = ~0U; ++ ctx->initialized = 1; ++ ctx->first_frame_sequence = 0; ++ ++ /* Update kfifo out pointer from coda bitstream read pointer */ ++ coda_kfifo_sync_from_device(ctx); ++ ++ /* ++ * After updating the read pointer, we need to check if ++ * any metas are consumed and should be released. ++ */ ++ coda_decoder_drop_used_metas(ctx); ++ ++ if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) { ++ v4l2_err(&dev->v4l2_dev, ++ "CODA_COMMAND_SEQ_INIT failed, error code = 0x%x\n", ++ coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON)); ++ return -EAGAIN; ++ } ++ ++ val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE); ++ if (dev->devtype->product == CODA_DX6) { ++ width = (val >> CODADX6_PICWIDTH_OFFSET) & CODADX6_PICWIDTH_MASK; ++ height = val & CODADX6_PICHEIGHT_MASK; ++ } else { ++ width = (val >> CODA7_PICWIDTH_OFFSET) & CODA7_PICWIDTH_MASK; ++ height = val & CODA7_PICHEIGHT_MASK; ++ } ++ ++ if (width > q_data_dst->bytesperline || height > q_data_dst->height) { ++ v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n", ++ width, height, q_data_dst->bytesperline, ++ q_data_dst->height); ++ return -EINVAL; ++ } ++ ++ width = round_up(width, 16); ++ height = round_up(height, 16); ++ ++ coda_dbg(1, ctx, "start decoding: %dx%d\n", width, height); ++ ++ ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED); ++ /* ++ * If the VDOA is used, the decoder needs one additional frame, ++ * because the frames are freed when the next frame is decoded. ++ * Otherwise there are visible errors in the decoded frames (green ++ * regions in displayed frames) and a broken order of frames (earlier ++ * frames are sporadically displayed after later frames). ++ */ ++ if (ctx->use_vdoa) ++ ctx->num_internal_frames += 1; ++ if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) { ++ v4l2_err(&dev->v4l2_dev, ++ "not enough framebuffers to decode (%d < %d)\n", ++ CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames); ++ return -EINVAL; ++ } ++ ++ if (src_fourcc == V4L2_PIX_FMT_H264) { ++ u32 left_right; ++ u32 top_bottom; ++ ++ left_right = coda_read(dev, CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT); ++ top_bottom = coda_read(dev, CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM); ++ ++ q_data_dst->rect.left = (left_right >> 10) & 0x3ff; ++ q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff; ++ q_data_dst->rect.width = width - q_data_dst->rect.left - ++ (left_right & 0x3ff); ++ q_data_dst->rect.height = height - q_data_dst->rect.top - ++ (top_bottom & 0x3ff); ++ } ++ ++ if (dev->devtype->product != CODA_DX6) { ++ u8 profile, level; ++ ++ val = coda_read(dev, CODA7_RET_DEC_SEQ_HEADER_REPORT); ++ profile = val & 0xff; ++ level = (val >> 8) & 0x7f; ++ ++ if (profile || level) ++ coda_update_profile_level_ctrls(ctx, profile, level); ++ } ++ ++ return 0; ++} ++ ++static void coda_dec_seq_init_work(struct work_struct *work) ++{ ++ struct coda_ctx *ctx = container_of(work, ++ struct coda_ctx, seq_init_work); ++ struct coda_dev *dev = ctx->dev; ++ ++ mutex_lock(&ctx->buffer_mutex); ++ mutex_lock(&dev->coda_mutex); ++ ++ if (!ctx->initialized) ++ __coda_decoder_seq_init(ctx); ++ ++ mutex_unlock(&dev->coda_mutex); ++ mutex_unlock(&ctx->buffer_mutex); ++} ++ ++static int __coda_start_decoding(struct coda_ctx *ctx) ++{ ++ struct coda_q_data *q_data_src, *q_data_dst; ++ struct coda_dev *dev = ctx->dev; ++ u32 src_fourcc, dst_fourcc; ++ int ret; ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ src_fourcc = q_data_src->fourcc; ++ dst_fourcc = q_data_dst->fourcc; ++ ++ if (!ctx->initialized) { ++ ret = __coda_decoder_seq_init(ctx); ++ if (ret < 0) ++ return ret; ++ } else { ++ ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) | ++ CODA9_FRAME_TILED2LINEAR); ++ if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV) ++ ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE; ++ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) ++ ctx->frame_mem_ctrl |= (0x3 << 9) | ++ ((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR); ++ } ++ ++ coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); ++ ++ ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, "failed to allocate framebuffers\n"); ++ return ret; ++ } ++ ++ /* Tell the decoder how many frame buffers we allocated. */ ++ coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); ++ coda_write(dev, round_up(q_data_dst->rect.width, 16), ++ CODA_CMD_SET_FRAME_BUF_STRIDE); ++ ++ if (dev->devtype->product != CODA_DX6) { ++ /* Set secondary AXI IRAM */ ++ coda_setup_iram(ctx); ++ ++ coda_write(dev, ctx->iram_info.buf_bit_use, ++ CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); ++ coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, ++ CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); ++ coda_write(dev, ctx->iram_info.buf_dbk_y_use, ++ CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); ++ coda_write(dev, ctx->iram_info.buf_dbk_c_use, ++ CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); ++ coda_write(dev, ctx->iram_info.buf_ovl_use, ++ CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); ++ if (dev->devtype->product == CODA_960) { ++ coda_write(dev, ctx->iram_info.buf_btp_use, ++ CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); ++ ++ coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY); ++ coda9_set_frame_cache(ctx, dst_fourcc); ++ } ++ } ++ ++ if (src_fourcc == V4L2_PIX_FMT_H264) { ++ coda_write(dev, ctx->slicebuf.paddr, ++ CODA_CMD_SET_FRAME_SLICE_BB_START); ++ coda_write(dev, ctx->slicebuf.size / 1024, ++ CODA_CMD_SET_FRAME_SLICE_BB_SIZE); ++ } ++ ++ if (dev->devtype->product == CODA_HX4 || ++ dev->devtype->product == CODA_7541) { ++ int max_mb_x = 1920 / 16; ++ int max_mb_y = 1088 / 16; ++ int max_mb_num = max_mb_x * max_mb_y; ++ ++ coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, ++ CODA7_CMD_SET_FRAME_MAX_DEC_SIZE); ++ } else if (dev->devtype->product == CODA_960) { ++ int max_mb_x = 1920 / 16; ++ int max_mb_y = 1088 / 16; ++ int max_mb_num = max_mb_x * max_mb_y; ++ ++ coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, ++ CODA9_CMD_SET_FRAME_MAX_DEC_SIZE); ++ } ++ ++ if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "CODA_COMMAND_SET_FRAME_BUF timeout\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static int coda_start_decoding(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ int ret; ++ ++ mutex_lock(&dev->coda_mutex); ++ ret = __coda_start_decoding(ctx); ++ mutex_unlock(&dev->coda_mutex); ++ ++ return ret; ++} ++ ++static int coda_prepare_decode(struct coda_ctx *ctx) ++{ ++ struct vb2_v4l2_buffer *dst_buf; ++ struct coda_dev *dev = ctx->dev; ++ struct coda_q_data *q_data_dst; ++ struct coda_buffer_meta *meta; ++ u32 rot_mode = 0; ++ u32 reg_addr, reg_stride; ++ ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ ++ /* Try to copy source buffer contents into the bitstream ringbuffer */ ++ mutex_lock(&ctx->bitstream_mutex); ++ coda_fill_bitstream(ctx, NULL); ++ mutex_unlock(&ctx->bitstream_mutex); ++ ++ if (coda_get_bitstream_payload(ctx) < 512 && ++ (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { ++ coda_dbg(1, ctx, "bitstream payload: %d, skipping\n", ++ coda_get_bitstream_payload(ctx)); ++ return -EAGAIN; ++ } ++ ++ /* Run coda_start_decoding (again) if not yet initialized */ ++ if (!ctx->initialized) { ++ int ret = __coda_start_decoding(ctx); ++ ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, "failed to start decoding\n"); ++ return -EAGAIN; ++ } else { ++ ctx->initialized = 1; ++ } ++ } ++ ++ if (dev->devtype->product == CODA_960) ++ coda_set_gdi_regs(ctx); ++ ++ if (ctx->use_vdoa && ++ ctx->display_idx >= 0 && ++ ctx->display_idx < ctx->num_internal_frames) { ++ vdoa_device_run(ctx->vdoa, ++ vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0), ++ ctx->internal_frames[ctx->display_idx].buf.paddr); ++ } else { ++ if (dev->devtype->product == CODA_960) { ++ /* ++ * It was previously assumed that the CODA960 has an ++ * internal list of 64 buffer entries that contains ++ * both the registered internal frame buffers as well ++ * as the rotator buffer output, and that the ROT_INDEX ++ * register must be set to a value between the last ++ * internal frame buffers' index and 64. ++ * At least on firmware version 3.1.1 it turns out that ++ * setting ROT_INDEX to any value >= 32 causes CODA ++ * hangups that it can not recover from with the SRC VPU ++ * reset. ++ * It does appear to work however, to just set it to a ++ * fixed value in the [ctx->num_internal_frames, 31] ++ * range, for example CODA_MAX_FRAMEBUFFERS. ++ */ ++ coda_write(dev, CODA_MAX_FRAMEBUFFERS, ++ CODA9_CMD_DEC_PIC_ROT_INDEX); ++ ++ reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y; ++ reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE; ++ } else { ++ reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y; ++ reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE; ++ } ++ coda_write_base(ctx, q_data_dst, dst_buf, reg_addr); ++ coda_write(dev, q_data_dst->bytesperline, reg_stride); ++ ++ rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode; ++ } ++ ++ coda_write(dev, rot_mode, CODA_CMD_DEC_PIC_ROT_MODE); ++ ++ switch (dev->devtype->product) { ++ case CODA_DX6: ++ /* TBD */ ++ case CODA_HX4: ++ case CODA_7541: ++ coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION); ++ break; ++ case CODA_960: ++ /* 'hardcode to use interrupt disable mode'? */ ++ coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); ++ break; ++ } ++ ++ coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM); ++ ++ coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START); ++ coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE); ++ ++ if (dev->devtype->product != CODA_DX6) ++ coda_write(dev, ctx->iram_info.axi_sram_use, ++ CODA7_REG_BIT_AXI_SRAM_USE); ++ ++ spin_lock(&ctx->buffer_meta_lock); ++ meta = list_first_entry_or_null(&ctx->buffer_meta_list, ++ struct coda_buffer_meta, list); ++ ++ if (meta && ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) { ++ ++ /* If this is the last buffer in the bitstream, add padding */ ++ if (meta->end == ctx->bitstream_fifo.kfifo.in) { ++ static unsigned char buf[512]; ++ unsigned int pad; ++ ++ /* Pad to multiple of 256 and then add 256 more */ ++ pad = ((0 - meta->end) & 0xff) + 256; ++ ++ memset(buf, 0xff, sizeof(buf)); ++ ++ kfifo_in(&ctx->bitstream_fifo, buf, pad); ++ } ++ } ++ spin_unlock(&ctx->buffer_meta_lock); ++ ++ coda_kfifo_sync_to_device_full(ctx); ++ ++ /* Clear decode success flag */ ++ coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS); ++ ++ /* Clear error return value */ ++ coda_write(dev, 0, CODA_RET_DEC_PIC_ERR_MB); ++ ++ trace_coda_dec_pic_run(ctx, meta); ++ ++ coda_command_async(ctx, CODA_COMMAND_PIC_RUN); ++ ++ return 0; ++} ++ ++static void coda_finish_decode(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ struct coda_q_data *q_data_src; ++ struct coda_q_data *q_data_dst; ++ struct vb2_v4l2_buffer *dst_buf; ++ struct coda_buffer_meta *meta; ++ int width, height; ++ int decoded_idx; ++ int display_idx; ++ struct coda_internal_frame *decoded_frame = NULL; ++ u32 src_fourcc; ++ int success; ++ u32 err_mb; ++ int err_vdoa = 0; ++ u32 val; ++ ++ if (ctx->aborting) ++ return; ++ ++ /* Update kfifo out pointer from coda bitstream read pointer */ ++ coda_kfifo_sync_from_device(ctx); ++ ++ /* ++ * in stream-end mode, the read pointer can overshoot the write pointer ++ * by up to 512 bytes ++ */ ++ if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) { ++ if (coda_get_bitstream_payload(ctx) >= ctx->bitstream.size - 512) ++ kfifo_init(&ctx->bitstream_fifo, ++ ctx->bitstream.vaddr, ctx->bitstream.size); ++ } ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ src_fourcc = q_data_src->fourcc; ++ ++ val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS); ++ if (val != 1) ++ pr_err("DEC_PIC_SUCCESS = %d\n", val); ++ ++ success = val & 0x1; ++ if (!success) ++ v4l2_err(&dev->v4l2_dev, "decode failed\n"); ++ ++ if (src_fourcc == V4L2_PIX_FMT_H264) { ++ if (val & (1 << 3)) ++ v4l2_err(&dev->v4l2_dev, ++ "insufficient PS buffer space (%d bytes)\n", ++ ctx->psbuf.size); ++ if (val & (1 << 2)) ++ v4l2_err(&dev->v4l2_dev, ++ "insufficient slice buffer space (%d bytes)\n", ++ ctx->slicebuf.size); ++ } ++ ++ val = coda_read(dev, CODA_RET_DEC_PIC_SIZE); ++ width = (val >> 16) & 0xffff; ++ height = val & 0xffff; ++ ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ ++ /* frame crop information */ ++ if (src_fourcc == V4L2_PIX_FMT_H264) { ++ u32 left_right; ++ u32 top_bottom; ++ ++ left_right = coda_read(dev, CODA_RET_DEC_PIC_CROP_LEFT_RIGHT); ++ top_bottom = coda_read(dev, CODA_RET_DEC_PIC_CROP_TOP_BOTTOM); ++ ++ if (left_right == 0xffffffff && top_bottom == 0xffffffff) { ++ /* Keep current crop information */ ++ } else { ++ struct v4l2_rect *rect = &q_data_dst->rect; ++ ++ rect->left = left_right >> 16 & 0xffff; ++ rect->top = top_bottom >> 16 & 0xffff; ++ rect->width = width - rect->left - ++ (left_right & 0xffff); ++ rect->height = height - rect->top - ++ (top_bottom & 0xffff); ++ } ++ } else { ++ /* no cropping */ ++ } ++ ++ err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); ++ if (err_mb > 0) { ++ if (__ratelimit(&dev->mb_err_rs)) ++ coda_dbg(1, ctx, "errors in %d macroblocks\n", err_mb); ++ v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, ++ v4l2_ctrl_g_ctrl(ctx->mb_err_cnt_ctrl) + err_mb); ++ } ++ ++ if (dev->devtype->product == CODA_HX4 || ++ dev->devtype->product == CODA_7541) { ++ val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); ++ if (val == 0) { ++ /* not enough bitstream data */ ++ coda_dbg(1, ctx, "prescan failed: %d\n", val); ++ ctx->hold = true; ++ return; ++ } ++ } ++ ++ /* Wait until the VDOA finished writing the previous display frame */ ++ if (ctx->use_vdoa && ++ ctx->display_idx >= 0 && ++ ctx->display_idx < ctx->num_internal_frames) { ++ err_vdoa = vdoa_wait_for_completion(ctx->vdoa); ++ } ++ ++ ctx->frm_dis_flg = coda_read(dev, ++ CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); ++ ++ /* The previous display frame was copied out and can be overwritten */ ++ if (ctx->display_idx >= 0 && ++ ctx->display_idx < ctx->num_internal_frames) { ++ ctx->frm_dis_flg &= ~(1 << ctx->display_idx); ++ coda_write(dev, ctx->frm_dis_flg, ++ CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); ++ } ++ ++ /* ++ * The index of the last decoded frame, not necessarily in ++ * display order, and the index of the next display frame. ++ * The latter could have been decoded in a previous run. ++ */ ++ decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX); ++ display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX); ++ ++ if (decoded_idx == -1) { ++ /* no frame was decoded, but we might have a display frame */ ++ if (display_idx >= 0 && display_idx < ctx->num_internal_frames) ++ ctx->sequence_offset++; ++ else if (ctx->display_idx < 0) ++ ctx->hold = true; ++ } else if (decoded_idx == -2) { ++ if (ctx->display_idx >= 0 && ++ ctx->display_idx < ctx->num_internal_frames) ++ ctx->sequence_offset++; ++ /* no frame was decoded, we still return remaining buffers */ ++ } else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) { ++ v4l2_err(&dev->v4l2_dev, ++ "decoded frame index out of range: %d\n", decoded_idx); ++ } else { ++ int sequence; ++ ++ decoded_frame = &ctx->internal_frames[decoded_idx]; ++ ++ val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM); ++ if (ctx->sequence_offset == -1) ++ ctx->sequence_offset = val; ++ ++ sequence = val + ctx->first_frame_sequence ++ - ctx->sequence_offset; ++ spin_lock(&ctx->buffer_meta_lock); ++ if (!list_empty(&ctx->buffer_meta_list)) { ++ meta = list_first_entry(&ctx->buffer_meta_list, ++ struct coda_buffer_meta, list); ++ list_del(&meta->list); ++ ctx->num_metas--; ++ spin_unlock(&ctx->buffer_meta_lock); ++ /* ++ * Clamp counters to 16 bits for comparison, as the HW ++ * counter rolls over at this point for h.264. This ++ * may be different for other formats, but using 16 bits ++ * should be enough to detect most errors and saves us ++ * from doing different things based on the format. ++ */ ++ if ((sequence & 0xffff) != (meta->sequence & 0xffff)) { ++ v4l2_err(&dev->v4l2_dev, ++ "sequence number mismatch (%d(%d) != %d)\n", ++ sequence, ctx->sequence_offset, ++ meta->sequence); ++ } ++ decoded_frame->meta = *meta; ++ kfree(meta); ++ } else { ++ spin_unlock(&ctx->buffer_meta_lock); ++ v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n"); ++ memset(&decoded_frame->meta, 0, ++ sizeof(struct coda_buffer_meta)); ++ decoded_frame->meta.sequence = sequence; ++ decoded_frame->meta.last = false; ++ ctx->sequence_offset++; ++ } ++ ++ trace_coda_dec_pic_done(ctx, &decoded_frame->meta); ++ ++ val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7; ++ decoded_frame->type = (val == 0) ? V4L2_BUF_FLAG_KEYFRAME : ++ (val == 1) ? V4L2_BUF_FLAG_PFRAME : ++ V4L2_BUF_FLAG_BFRAME; ++ ++ decoded_frame->error = err_mb; ++ } ++ ++ if (display_idx == -1) { ++ /* ++ * no more frames to be decoded, but there could still ++ * be rotator output to dequeue ++ */ ++ ctx->hold = true; ++ } else if (display_idx == -3) { ++ /* possibly prescan failure */ ++ } else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) { ++ v4l2_err(&dev->v4l2_dev, ++ "presentation frame index out of range: %d\n", ++ display_idx); ++ } ++ ++ /* If a frame was copied out, return it */ ++ if (ctx->display_idx >= 0 && ++ ctx->display_idx < ctx->num_internal_frames) { ++ struct coda_internal_frame *ready_frame; ++ ++ ready_frame = &ctx->internal_frames[ctx->display_idx]; ++ ++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); ++ dst_buf->sequence = ctx->osequence++; ++ ++ dst_buf->field = V4L2_FIELD_NONE; ++ dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | ++ V4L2_BUF_FLAG_PFRAME | ++ V4L2_BUF_FLAG_BFRAME); ++ dst_buf->flags |= ready_frame->type; ++ meta = &ready_frame->meta; ++ if (meta->last && !coda_reorder_enable(ctx)) { ++ /* ++ * If this was the last decoded frame, and reordering ++ * is disabled, this will be the last display frame. ++ */ ++ coda_dbg(1, ctx, "last meta, marking as last frame\n"); ++ dst_buf->flags |= V4L2_BUF_FLAG_LAST; ++ } else if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG && ++ display_idx == -1) { ++ /* ++ * If there is no designated presentation frame anymore, ++ * this frame has to be the last one. ++ */ ++ coda_dbg(1, ctx, ++ "no more frames to return, marking as last frame\n"); ++ dst_buf->flags |= V4L2_BUF_FLAG_LAST; ++ } ++ dst_buf->timecode = meta->timecode; ++ dst_buf->vb2_buf.timestamp = meta->timestamp; ++ ++ trace_coda_dec_rot_done(ctx, dst_buf, meta); ++ ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, ++ q_data_dst->sizeimage); ++ ++ if (ready_frame->error || err_vdoa) ++ coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR); ++ else ++ coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE); ++ ++ if (decoded_frame) { ++ coda_dbg(1, ctx, "job finished: decoded %c frame %u, returned %c frame %u (%u/%u)%s\n", ++ coda_frame_type_char(decoded_frame->type), ++ decoded_frame->meta.sequence, ++ coda_frame_type_char(dst_buf->flags), ++ ready_frame->meta.sequence, ++ dst_buf->sequence, ctx->qsequence, ++ (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? ++ " (last)" : ""); ++ } else { ++ coda_dbg(1, ctx, "job finished: no frame decoded (%d), returned %c frame %u (%u/%u)%s\n", ++ decoded_idx, ++ coda_frame_type_char(dst_buf->flags), ++ ready_frame->meta.sequence, ++ dst_buf->sequence, ctx->qsequence, ++ (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? ++ " (last)" : ""); ++ } ++ } else { ++ if (decoded_frame) { ++ coda_dbg(1, ctx, "job finished: decoded %c frame %u, no frame returned (%d)\n", ++ coda_frame_type_char(decoded_frame->type), ++ decoded_frame->meta.sequence, ++ ctx->display_idx); ++ } else { ++ coda_dbg(1, ctx, "job finished: no frame decoded (%d) or returned (%d)\n", ++ decoded_idx, ctx->display_idx); ++ } ++ } ++ ++ /* The rotator will copy the current display frame next time */ ++ ctx->display_idx = display_idx; ++ ++ /* ++ * The current decode run might have brought the bitstream fill level ++ * below the size where we can start the next decode run. As userspace ++ * might have filled the output queue completely and might thus be ++ * blocked, we can't rely on the next qbuf to trigger the bitstream ++ * refill. Check if we have data to refill the bitstream now. ++ */ ++ mutex_lock(&ctx->bitstream_mutex); ++ coda_fill_bitstream(ctx, NULL); ++ mutex_unlock(&ctx->bitstream_mutex); ++} ++ ++static void coda_decode_timeout(struct coda_ctx *ctx) ++{ ++ struct vb2_v4l2_buffer *dst_buf; ++ ++ /* ++ * For now this only handles the case where we would deadlock with ++ * userspace, i.e. userspace issued DEC_CMD_STOP and waits for EOS, ++ * but after a failed decode run we would hold the context and wait for ++ * userspace to queue more buffers. ++ */ ++ if (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)) ++ return; ++ ++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); ++ dst_buf->sequence = ctx->qsequence - 1; ++ ++ coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR); ++} ++ ++const struct coda_context_ops coda_bit_decode_ops = { ++ .queue_init = coda_decoder_queue_init, ++ .reqbufs = coda_decoder_reqbufs, ++ .start_streaming = coda_start_decoding, ++ .prepare_run = coda_prepare_decode, ++ .finish_run = coda_finish_decode, ++ .run_timeout = coda_decode_timeout, ++ .seq_init_work = coda_dec_seq_init_work, ++ .seq_end_work = coda_seq_end_work, ++ .release = coda_bit_release, ++}; ++ ++irqreturn_t coda_irq_handler(int irq, void *data) ++{ ++ struct coda_dev *dev = data; ++ struct coda_ctx *ctx; ++ ++ /* read status register to attend the IRQ */ ++ coda_read(dev, CODA_REG_BIT_INT_STATUS); ++ coda_write(dev, 0, CODA_REG_BIT_INT_REASON); ++ coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, ++ CODA_REG_BIT_INT_CLEAR); ++ ++ ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); ++ if (ctx == NULL) { ++ v4l2_err(&dev->v4l2_dev, ++ "Instance released before the end of transaction\n"); ++ return IRQ_HANDLED; ++ } ++ ++ trace_coda_bit_done(ctx); ++ ++ if (ctx->aborting) { ++ coda_dbg(1, ctx, "task has been aborted\n"); ++ } ++ ++ if (coda_isbusy(ctx->dev)) { ++ coda_dbg(1, ctx, "coda is still busy!!!!\n"); ++ return IRQ_NONE; ++ } ++ ++ complete(&ctx->completion); ++ ++ return IRQ_HANDLED; ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-common.c b/drivers/media/platform/chips-media/coda/coda-common.c +--- a/drivers/media/platform/chips-media/coda/coda-common.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda-common.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,3361 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Coda multi-standard codec IP ++ * ++ * Copyright (C) 2012 Vista Silicon S.L. ++ * Javier Martin, ++ * Xavier Duret ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coda.h" ++#include "imx-vdoa.h" ++ ++#define CODA_NAME "coda" ++ ++#define CODADX6_MAX_INSTANCES 4 ++#define CODA_MAX_FORMATS 5 ++ ++#define CODA_ISRAM_SIZE (2048 * 2) ++ ++#define MIN_W 48 ++#define MIN_H 16 ++ ++#define S_ALIGN 1 /* multiple of 2 */ ++#define W_ALIGN 1 /* multiple of 2 */ ++#define H_ALIGN 1 /* multiple of 2 */ ++ ++#define fh_to_ctx(__fh) container_of(__fh, struct coda_ctx, fh) ++ ++int coda_debug; ++module_param(coda_debug, int, 0644); ++MODULE_PARM_DESC(coda_debug, "Debug level (0-2)"); ++ ++static int disable_tiling; ++module_param(disable_tiling, int, 0644); ++MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers"); ++ ++static int disable_vdoa; ++module_param(disable_vdoa, int, 0644); ++MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster-scan conversion"); ++ ++static int enable_bwb = 0; ++module_param(enable_bwb, int, 0644); ++MODULE_PARM_DESC(enable_bwb, "Enable BWB unit for decoding, may crash on certain streams"); ++ ++void coda_write(struct coda_dev *dev, u32 data, u32 reg) ++{ ++ v4l2_dbg(3, coda_debug, &dev->v4l2_dev, ++ "%s: data=0x%x, reg=0x%x\n", __func__, data, reg); ++ writel(data, dev->regs_base + reg); ++} ++ ++unsigned int coda_read(struct coda_dev *dev, u32 reg) ++{ ++ u32 data; ++ ++ data = readl(dev->regs_base + reg); ++ v4l2_dbg(3, coda_debug, &dev->v4l2_dev, ++ "%s: data=0x%x, reg=0x%x\n", __func__, data, reg); ++ return data; ++} ++ ++void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data, ++ struct vb2_v4l2_buffer *buf, unsigned int reg_y) ++{ ++ u32 base_y = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0); ++ u32 base_cb, base_cr; ++ ++ switch (q_data->fourcc) { ++ case V4L2_PIX_FMT_YUYV: ++ /* Fallthrough: IN -H264-> CODA -NV12 MB-> VDOA -YUYV-> OUT */ ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_YUV420: ++ default: ++ base_cb = base_y + q_data->bytesperline * q_data->height; ++ base_cr = base_cb + q_data->bytesperline * q_data->height / 4; ++ break; ++ case V4L2_PIX_FMT_YVU420: ++ /* Switch Cb and Cr for YVU420 format */ ++ base_cr = base_y + q_data->bytesperline * q_data->height; ++ base_cb = base_cr + q_data->bytesperline * q_data->height / 4; ++ break; ++ case V4L2_PIX_FMT_YUV422P: ++ base_cb = base_y + q_data->bytesperline * q_data->height; ++ base_cr = base_cb + q_data->bytesperline * q_data->height / 2; ++ } ++ ++ coda_write(ctx->dev, base_y, reg_y); ++ coda_write(ctx->dev, base_cb, reg_y + 4); ++ coda_write(ctx->dev, base_cr, reg_y + 8); ++} ++ ++#define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \ ++ { mode, src_fourcc, dst_fourcc, max_w, max_h } ++ ++/* ++ * Arrays of codecs supported by each given version of Coda: ++ * i.MX27 -> codadx6 ++ * i.MX51 -> codahx4 ++ * i.MX53 -> coda7 ++ * i.MX6 -> coda960 ++ * Use V4L2_PIX_FMT_YUV420 as placeholder for all supported YUV 4:2:0 variants ++ */ ++static const struct coda_codec codadx6_codecs[] = { ++ CODA_CODEC(CODADX6_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 720, 576), ++ CODA_CODEC(CODADX6_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 720, 576), ++}; ++ ++static const struct coda_codec codahx4_codecs[] = { ++ CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 720, 576), ++ CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), ++ CODA_CODEC(CODA7_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), ++ CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1280, 720), ++}; ++ ++static const struct coda_codec coda7_codecs[] = { ++ CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720), ++ CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), ++ CODA_CODEC(CODA7_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG, 8192, 8192), ++ CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), ++ CODA_CODEC(CODA7_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), ++ CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), ++ CODA_CODEC(CODA7_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420, 8192, 8192), ++}; ++ ++static const struct coda_codec coda9_codecs[] = { ++ CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1920, 1088), ++ CODA_CODEC(CODA9_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1920, 1088), ++ CODA_CODEC(CODA9_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG, 8192, 8192), ++ CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), ++ CODA_CODEC(CODA9_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), ++ CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), ++ CODA_CODEC(CODA9_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420, 8192, 8192), ++}; ++ ++struct coda_video_device { ++ const char *name; ++ enum coda_inst_type type; ++ const struct coda_context_ops *ops; ++ bool direct; ++ u32 src_formats[CODA_MAX_FORMATS]; ++ u32 dst_formats[CODA_MAX_FORMATS]; ++}; ++ ++static const struct coda_video_device coda_bit_encoder = { ++ .name = "coda-video-encoder", ++ .type = CODA_INST_ENCODER, ++ .ops = &coda_bit_encode_ops, ++ .src_formats = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_YUV420, ++ V4L2_PIX_FMT_YVU420, ++ }, ++ .dst_formats = { ++ V4L2_PIX_FMT_H264, ++ V4L2_PIX_FMT_MPEG4, ++ }, ++}; ++ ++static const struct coda_video_device coda_bit_jpeg_encoder = { ++ .name = "coda-jpeg-encoder", ++ .type = CODA_INST_ENCODER, ++ .ops = &coda_bit_encode_ops, ++ .src_formats = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_YUV420, ++ V4L2_PIX_FMT_YVU420, ++ V4L2_PIX_FMT_YUV422P, ++ }, ++ .dst_formats = { ++ V4L2_PIX_FMT_JPEG, ++ }, ++}; ++ ++static const struct coda_video_device coda_bit_decoder = { ++ .name = "coda-video-decoder", ++ .type = CODA_INST_DECODER, ++ .ops = &coda_bit_decode_ops, ++ .src_formats = { ++ V4L2_PIX_FMT_H264, ++ V4L2_PIX_FMT_MPEG2, ++ V4L2_PIX_FMT_MPEG4, ++ }, ++ .dst_formats = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_YUV420, ++ V4L2_PIX_FMT_YVU420, ++ /* ++ * If V4L2_PIX_FMT_YUYV should be default, ++ * set_default_params() must be adjusted. ++ */ ++ V4L2_PIX_FMT_YUYV, ++ }, ++}; ++ ++static const struct coda_video_device coda_bit_jpeg_decoder = { ++ .name = "coda-jpeg-decoder", ++ .type = CODA_INST_DECODER, ++ .ops = &coda_bit_decode_ops, ++ .src_formats = { ++ V4L2_PIX_FMT_JPEG, ++ }, ++ .dst_formats = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_YUV420, ++ V4L2_PIX_FMT_YVU420, ++ V4L2_PIX_FMT_YUV422P, ++ }, ++}; ++ ++static const struct coda_video_device coda9_jpeg_encoder = { ++ .name = "coda-jpeg-encoder", ++ .type = CODA_INST_ENCODER, ++ .ops = &coda9_jpeg_encode_ops, ++ .direct = true, ++ .src_formats = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_YUV420, ++ V4L2_PIX_FMT_YVU420, ++ V4L2_PIX_FMT_YUV422P, ++ V4L2_PIX_FMT_GREY, ++ }, ++ .dst_formats = { ++ V4L2_PIX_FMT_JPEG, ++ }, ++}; ++ ++static const struct coda_video_device coda9_jpeg_decoder = { ++ .name = "coda-jpeg-decoder", ++ .type = CODA_INST_DECODER, ++ .ops = &coda9_jpeg_decode_ops, ++ .direct = true, ++ .src_formats = { ++ V4L2_PIX_FMT_JPEG, ++ }, ++ .dst_formats = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_YUV420, ++ V4L2_PIX_FMT_YVU420, ++ V4L2_PIX_FMT_YUV422P, ++ }, ++}; ++ ++static const struct coda_video_device *codadx6_video_devices[] = { ++ &coda_bit_encoder, ++}; ++ ++static const struct coda_video_device *codahx4_video_devices[] = { ++ &coda_bit_encoder, ++ &coda_bit_decoder, ++}; ++ ++static const struct coda_video_device *coda7_video_devices[] = { ++ &coda_bit_jpeg_encoder, ++ &coda_bit_jpeg_decoder, ++ &coda_bit_encoder, ++ &coda_bit_decoder, ++}; ++ ++static const struct coda_video_device *coda9_video_devices[] = { ++ &coda9_jpeg_encoder, ++ &coda9_jpeg_decoder, ++ &coda_bit_encoder, ++ &coda_bit_decoder, ++}; ++ ++/* ++ * Normalize all supported YUV 4:2:0 formats to the value used in the codec ++ * tables. ++ */ ++static u32 coda_format_normalize_yuv(u32 fourcc) ++{ ++ switch (fourcc) { ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_YUV420: ++ case V4L2_PIX_FMT_YVU420: ++ case V4L2_PIX_FMT_YUV422P: ++ case V4L2_PIX_FMT_YUYV: ++ return V4L2_PIX_FMT_YUV420; ++ default: ++ return fourcc; ++ } ++} ++ ++static const struct coda_codec *coda_find_codec(struct coda_dev *dev, ++ int src_fourcc, int dst_fourcc) ++{ ++ const struct coda_codec *codecs = dev->devtype->codecs; ++ int num_codecs = dev->devtype->num_codecs; ++ int k; ++ ++ src_fourcc = coda_format_normalize_yuv(src_fourcc); ++ dst_fourcc = coda_format_normalize_yuv(dst_fourcc); ++ if (src_fourcc == dst_fourcc) ++ return NULL; ++ ++ for (k = 0; k < num_codecs; k++) { ++ if (codecs[k].src_fourcc == src_fourcc && ++ codecs[k].dst_fourcc == dst_fourcc) ++ break; ++ } ++ ++ if (k == num_codecs) ++ return NULL; ++ ++ return &codecs[k]; ++} ++ ++static void coda_get_max_dimensions(struct coda_dev *dev, ++ const struct coda_codec *codec, ++ int *max_w, int *max_h) ++{ ++ const struct coda_codec *codecs = dev->devtype->codecs; ++ int num_codecs = dev->devtype->num_codecs; ++ unsigned int w, h; ++ int k; ++ ++ if (codec) { ++ w = codec->max_w; ++ h = codec->max_h; ++ } else { ++ for (k = 0, w = 0, h = 0; k < num_codecs; k++) { ++ w = max(w, codecs[k].max_w); ++ h = max(h, codecs[k].max_h); ++ } ++ } ++ ++ if (max_w) ++ *max_w = w; ++ if (max_h) ++ *max_h = h; ++} ++ ++static const struct coda_video_device *to_coda_video_device(struct video_device ++ *vdev) ++{ ++ struct coda_dev *dev = video_get_drvdata(vdev); ++ unsigned int i = vdev - dev->vfd; ++ ++ if (i >= dev->devtype->num_vdevs) ++ return NULL; ++ ++ return dev->devtype->vdevs[i]; ++} ++ ++const char *coda_product_name(int product) ++{ ++ static char buf[9]; ++ ++ switch (product) { ++ case CODA_DX6: ++ return "CodaDx6"; ++ case CODA_HX4: ++ return "CodaHx4"; ++ case CODA_7541: ++ return "CODA7541"; ++ case CODA_960: ++ return "CODA960"; ++ default: ++ snprintf(buf, sizeof(buf), "(0x%04x)", product); ++ return buf; ++ } ++} ++ ++static struct vdoa_data *coda_get_vdoa_data(void) ++{ ++ struct device_node *vdoa_node; ++ struct platform_device *vdoa_pdev; ++ struct vdoa_data *vdoa_data = NULL; ++ ++ vdoa_node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-vdoa"); ++ if (!vdoa_node) ++ return NULL; ++ ++ vdoa_pdev = of_find_device_by_node(vdoa_node); ++ if (!vdoa_pdev) ++ goto out; ++ ++ vdoa_data = platform_get_drvdata(vdoa_pdev); ++ if (!vdoa_data) ++ vdoa_data = ERR_PTR(-EPROBE_DEFER); ++ ++ put_device(&vdoa_pdev->dev); ++out: ++ of_node_put(vdoa_node); ++ ++ return vdoa_data; ++} ++ ++/* ++ * V4L2 ioctl() operations. ++ */ ++static int coda_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ ++ strscpy(cap->driver, CODA_NAME, sizeof(cap->driver)); ++ strscpy(cap->card, coda_product_name(ctx->dev->devtype->product), ++ sizeof(cap->card)); ++ strscpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info)); ++ return 0; ++} ++ ++static const u32 coda_formats_420[CODA_MAX_FORMATS] = { ++ V4L2_PIX_FMT_NV12, ++ V4L2_PIX_FMT_YUV420, ++ V4L2_PIX_FMT_YVU420, ++}; ++ ++static int coda_enum_fmt(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ struct video_device *vdev = video_devdata(file); ++ const struct coda_video_device *cvd = to_coda_video_device(vdev); ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ const u32 *formats; ++ ++ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ formats = cvd->src_formats; ++ else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { ++ struct coda_q_data *q_data_src; ++ struct vb2_queue *src_vq; ++ ++ formats = cvd->dst_formats; ++ ++ /* ++ * If the source format is already fixed, only allow the same ++ * chroma subsampling. ++ */ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, ++ V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG && ++ vb2_is_streaming(src_vq)) { ++ if (ctx->params.jpeg_chroma_subsampling == ++ V4L2_JPEG_CHROMA_SUBSAMPLING_420) { ++ formats = coda_formats_420; ++ } else if (ctx->params.jpeg_chroma_subsampling == ++ V4L2_JPEG_CHROMA_SUBSAMPLING_422) { ++ f->pixelformat = V4L2_PIX_FMT_YUV422P; ++ return f->index ? -EINVAL : 0; ++ } ++ } ++ } else { ++ return -EINVAL; ++ } ++ ++ if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0) ++ return -EINVAL; ++ ++ /* Skip YUYV if the vdoa is not available */ ++ if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ formats[f->index] == V4L2_PIX_FMT_YUYV) ++ return -EINVAL; ++ ++ f->pixelformat = formats[f->index]; ++ ++ return 0; ++} ++ ++static int coda_g_fmt(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct coda_q_data *q_data; ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ ++ q_data = get_q_data(ctx, f->type); ++ if (!q_data) ++ return -EINVAL; ++ ++ f->fmt.pix.field = V4L2_FIELD_NONE; ++ f->fmt.pix.pixelformat = q_data->fourcc; ++ f->fmt.pix.width = q_data->width; ++ f->fmt.pix.height = q_data->height; ++ f->fmt.pix.bytesperline = q_data->bytesperline; ++ ++ f->fmt.pix.sizeimage = q_data->sizeimage; ++ f->fmt.pix.colorspace = ctx->colorspace; ++ f->fmt.pix.xfer_func = ctx->xfer_func; ++ f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; ++ f->fmt.pix.quantization = ctx->quantization; ++ ++ return 0; ++} ++ ++static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f) ++{ ++ struct coda_q_data *q_data; ++ const u32 *formats; ++ int i; ++ ++ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ formats = ctx->cvd->src_formats; ++ else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ formats = ctx->cvd->dst_formats; ++ else ++ return -EINVAL; ++ ++ for (i = 0; i < CODA_MAX_FORMATS; i++) { ++ /* Skip YUYV if the vdoa is not available */ ++ if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && ++ formats[i] == V4L2_PIX_FMT_YUYV) ++ continue; ++ ++ if (formats[i] == f->fmt.pix.pixelformat) { ++ f->fmt.pix.pixelformat = formats[i]; ++ return 0; ++ } ++ } ++ ++ /* Fall back to currently set pixelformat */ ++ q_data = get_q_data(ctx, f->type); ++ f->fmt.pix.pixelformat = q_data->fourcc; ++ ++ return 0; ++} ++ ++static int coda_try_fmt_vdoa(struct coda_ctx *ctx, struct v4l2_format *f, ++ bool *use_vdoa) ++{ ++ int err; ++ ++ if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ if (!use_vdoa) ++ return -EINVAL; ++ ++ if (!ctx->vdoa) { ++ *use_vdoa = false; ++ return 0; ++ } ++ ++ err = vdoa_context_configure(NULL, round_up(f->fmt.pix.width, 16), ++ f->fmt.pix.height, f->fmt.pix.pixelformat); ++ if (err) { ++ *use_vdoa = false; ++ return 0; ++ } ++ ++ *use_vdoa = true; ++ return 0; ++} ++ ++static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage, ++ u32 width, u32 height) ++{ ++ /* ++ * This is a rough estimate for sensible compressed buffer ++ * sizes (between 1 and 16 bits per pixel). This could be ++ * improved by better format specific worst case estimates. ++ */ ++ return round_up(clamp(sizeimage, width * height / 8, ++ width * height * 2), PAGE_SIZE); ++} ++ ++static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, ++ struct v4l2_format *f) ++{ ++ struct coda_dev *dev = ctx->dev; ++ unsigned int max_w, max_h; ++ enum v4l2_field field; ++ ++ field = f->fmt.pix.field; ++ if (field == V4L2_FIELD_ANY) ++ field = V4L2_FIELD_NONE; ++ else if (V4L2_FIELD_NONE != field) ++ return -EINVAL; ++ ++ /* V4L2 specification suggests the driver corrects the format struct ++ * if any of the dimensions is unsupported */ ++ f->fmt.pix.field = field; ++ ++ coda_get_max_dimensions(dev, codec, &max_w, &max_h); ++ v4l_bound_align_image(&f->fmt.pix.width, MIN_W, max_w, W_ALIGN, ++ &f->fmt.pix.height, MIN_H, max_h, H_ALIGN, ++ S_ALIGN); ++ ++ switch (f->fmt.pix.pixelformat) { ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_YUV420: ++ case V4L2_PIX_FMT_YVU420: ++ /* ++ * Frame stride must be at least multiple of 8, ++ * but multiple of 16 for h.264 or JPEG 4:2:x ++ */ ++ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); ++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * ++ f->fmt.pix.height * 3 / 2; ++ break; ++ case V4L2_PIX_FMT_YUYV: ++ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2; ++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * ++ f->fmt.pix.height; ++ break; ++ case V4L2_PIX_FMT_YUV422P: ++ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); ++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * ++ f->fmt.pix.height * 2; ++ break; ++ case V4L2_PIX_FMT_GREY: ++ /* keep 16 pixel alignment of 8-bit pixel data */ ++ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); ++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; ++ break; ++ case V4L2_PIX_FMT_JPEG: ++ case V4L2_PIX_FMT_H264: ++ case V4L2_PIX_FMT_MPEG4: ++ case V4L2_PIX_FMT_MPEG2: ++ f->fmt.pix.bytesperline = 0; ++ f->fmt.pix.sizeimage = coda_estimate_sizeimage(ctx, ++ f->fmt.pix.sizeimage, ++ f->fmt.pix.width, ++ f->fmt.pix.height); ++ break; ++ default: ++ BUG(); ++ } ++ ++ return 0; ++} ++ ++static int coda_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ const struct coda_q_data *q_data_src; ++ const struct coda_codec *codec; ++ struct vb2_queue *src_vq; ++ int hscale = 0; ++ int vscale = 0; ++ int ret; ++ bool use_vdoa; ++ ++ ret = coda_try_pixelformat(ctx, f); ++ if (ret < 0) ++ return ret; ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ ++ /* ++ * If the source format is already fixed, only allow the same output ++ * resolution. When decoding JPEG images, we also have to make sure to ++ * use the same chroma subsampling. ++ */ ++ src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ if (vb2_is_streaming(src_vq)) { ++ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG && ++ ctx->dev->devtype->product == CODA_960) { ++ hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width); ++ vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height); ++ } ++ f->fmt.pix.width = q_data_src->width >> hscale; ++ f->fmt.pix.height = q_data_src->height >> vscale; ++ ++ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) { ++ if (ctx->params.jpeg_chroma_subsampling == ++ V4L2_JPEG_CHROMA_SUBSAMPLING_420 && ++ f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) ++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12; ++ else if (ctx->params.jpeg_chroma_subsampling == ++ V4L2_JPEG_CHROMA_SUBSAMPLING_422) ++ f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; ++ } ++ } ++ ++ f->fmt.pix.colorspace = ctx->colorspace; ++ f->fmt.pix.xfer_func = ctx->xfer_func; ++ f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; ++ f->fmt.pix.quantization = ctx->quantization; ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ codec = coda_find_codec(ctx->dev, q_data_src->fourcc, ++ f->fmt.pix.pixelformat); ++ if (!codec) ++ return -EINVAL; ++ ++ ret = coda_try_fmt(ctx, codec, f); ++ if (ret < 0) ++ return ret; ++ ++ /* The decoders always write complete macroblocks or MCUs */ ++ if (ctx->inst_type == CODA_INST_DECODER) { ++ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16 >> hscale); ++ f->fmt.pix.height = round_up(f->fmt.pix.height, 16 >> vscale); ++ if (codec->src_fourcc == V4L2_PIX_FMT_JPEG && ++ f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) { ++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * ++ f->fmt.pix.height * 2; ++ } else { ++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * ++ f->fmt.pix.height * 3 / 2; ++ } ++ ++ ret = coda_try_fmt_vdoa(ctx, f, &use_vdoa); ++ if (ret < 0) ++ return ret; ++ ++ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { ++ if (!use_vdoa) ++ return -EINVAL; ++ ++ f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2; ++ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * ++ f->fmt.pix.height; ++ } ++ } ++ ++ return 0; ++} ++ ++static void coda_set_default_colorspace(struct v4l2_pix_format *fmt) ++{ ++ enum v4l2_colorspace colorspace; ++ ++ if (fmt->pixelformat == V4L2_PIX_FMT_JPEG) ++ colorspace = V4L2_COLORSPACE_JPEG; ++ else if (fmt->width <= 720 && fmt->height <= 576) ++ colorspace = V4L2_COLORSPACE_SMPTE170M; ++ else ++ colorspace = V4L2_COLORSPACE_REC709; ++ ++ fmt->colorspace = colorspace; ++ fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; ++ fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; ++ fmt->quantization = V4L2_QUANTIZATION_DEFAULT; ++} ++ ++static int coda_try_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ struct coda_dev *dev = ctx->dev; ++ const struct coda_q_data *q_data_dst; ++ const struct coda_codec *codec; ++ int ret; ++ ++ ret = coda_try_pixelformat(ctx, f); ++ if (ret < 0) ++ return ret; ++ ++ if (f->fmt.pix.colorspace == V4L2_COLORSPACE_DEFAULT) ++ coda_set_default_colorspace(&f->fmt.pix); ++ ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc); ++ ++ return coda_try_fmt(ctx, codec, f); ++} ++ ++static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f, ++ struct v4l2_rect *r) ++{ ++ struct coda_q_data *q_data; ++ struct vb2_queue *vq; ++ ++ vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); ++ if (!vq) ++ return -EINVAL; ++ ++ q_data = get_q_data(ctx, f->type); ++ if (!q_data) ++ return -EINVAL; ++ ++ if (vb2_is_busy(vq)) { ++ v4l2_err(&ctx->dev->v4l2_dev, "%s: %s queue busy: %d\n", ++ __func__, v4l2_type_names[f->type], vq->num_buffers); ++ return -EBUSY; ++ } ++ ++ q_data->fourcc = f->fmt.pix.pixelformat; ++ q_data->width = f->fmt.pix.width; ++ q_data->height = f->fmt.pix.height; ++ q_data->bytesperline = f->fmt.pix.bytesperline; ++ q_data->sizeimage = f->fmt.pix.sizeimage; ++ if (r) { ++ q_data->rect = *r; ++ } else { ++ q_data->rect.left = 0; ++ q_data->rect.top = 0; ++ q_data->rect.width = f->fmt.pix.width; ++ q_data->rect.height = f->fmt.pix.height; ++ } ++ ++ switch (f->fmt.pix.pixelformat) { ++ case V4L2_PIX_FMT_YUYV: ++ ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP; ++ break; ++ case V4L2_PIX_FMT_NV12: ++ if (!disable_tiling && ctx->use_bit && ++ ctx->dev->devtype->product == CODA_960) { ++ ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP; ++ break; ++ } ++ fallthrough; ++ case V4L2_PIX_FMT_YUV420: ++ case V4L2_PIX_FMT_YVU420: ++ case V4L2_PIX_FMT_YUV422P: ++ ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP; ++ break; ++ default: ++ break; ++ } ++ ++ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP && ++ !coda_try_fmt_vdoa(ctx, f, &ctx->use_vdoa) && ++ ctx->use_vdoa) ++ vdoa_context_configure(ctx->vdoa, ++ round_up(f->fmt.pix.width, 16), ++ f->fmt.pix.height, ++ f->fmt.pix.pixelformat); ++ else ++ ctx->use_vdoa = false; ++ ++ coda_dbg(1, ctx, "Setting %s format, wxh: %dx%d, fmt: %4.4s %c\n", ++ v4l2_type_names[f->type], q_data->width, q_data->height, ++ (char *)&q_data->fourcc, ++ (ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) ? 'L' : 'T'); ++ ++ return 0; ++} ++ ++static int coda_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ struct coda_q_data *q_data_src; ++ const struct coda_codec *codec; ++ struct v4l2_rect r; ++ int hscale = 0; ++ int vscale = 0; ++ int ret; ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ ++ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG && ++ ctx->dev->devtype->product == CODA_960) { ++ hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width); ++ vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height); ++ } ++ ++ ret = coda_try_fmt_vid_cap(file, priv, f); ++ if (ret) ++ return ret; ++ ++ r.left = 0; ++ r.top = 0; ++ r.width = q_data_src->width >> hscale; ++ r.height = q_data_src->height >> vscale; ++ ++ ret = coda_s_fmt(ctx, f, &r); ++ if (ret) ++ return ret; ++ ++ if (ctx->inst_type != CODA_INST_ENCODER) ++ return 0; ++ ++ /* Setting the coded format determines the selected codec */ ++ codec = coda_find_codec(ctx->dev, q_data_src->fourcc, ++ f->fmt.pix.pixelformat); ++ if (!codec) { ++ v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n"); ++ return -EINVAL; ++ } ++ ctx->codec = codec; ++ ++ ctx->colorspace = f->fmt.pix.colorspace; ++ ctx->xfer_func = f->fmt.pix.xfer_func; ++ ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; ++ ctx->quantization = f->fmt.pix.quantization; ++ ++ return 0; ++} ++ ++static int coda_s_fmt_vid_out(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ const struct coda_codec *codec; ++ struct v4l2_format f_cap; ++ struct vb2_queue *dst_vq; ++ int ret; ++ ++ ret = coda_try_fmt_vid_out(file, priv, f); ++ if (ret) ++ return ret; ++ ++ ret = coda_s_fmt(ctx, f, NULL); ++ if (ret) ++ return ret; ++ ++ ctx->colorspace = f->fmt.pix.colorspace; ++ ctx->xfer_func = f->fmt.pix.xfer_func; ++ ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; ++ ctx->quantization = f->fmt.pix.quantization; ++ ++ if (ctx->inst_type != CODA_INST_DECODER) ++ return 0; ++ ++ /* Setting the coded format determines the selected codec */ ++ codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat, ++ V4L2_PIX_FMT_YUV420); ++ if (!codec) { ++ v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n"); ++ return -EINVAL; ++ } ++ ctx->codec = codec; ++ ++ dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ if (!dst_vq) ++ return -EINVAL; ++ ++ /* ++ * Setting the capture queue format is not possible while the capture ++ * queue is still busy. This is not an error, but the user will have to ++ * make sure themselves that the capture format is set correctly before ++ * starting the output queue again. ++ */ ++ if (vb2_is_busy(dst_vq)) ++ return 0; ++ ++ memset(&f_cap, 0, sizeof(f_cap)); ++ f_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ coda_g_fmt(file, priv, &f_cap); ++ f_cap.fmt.pix.width = f->fmt.pix.width; ++ f_cap.fmt.pix.height = f->fmt.pix.height; ++ ++ return coda_s_fmt_vid_cap(file, priv, &f_cap); ++} ++ ++static int coda_reqbufs(struct file *file, void *priv, ++ struct v4l2_requestbuffers *rb) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ int ret; ++ ++ ret = v4l2_m2m_reqbufs(file, ctx->fh.m2m_ctx, rb); ++ if (ret) ++ return ret; ++ ++ /* ++ * Allow to allocate instance specific per-context buffers, such as ++ * bitstream ringbuffer, slice buffer, work buffer, etc. if needed. ++ */ ++ if (rb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && ctx->ops->reqbufs) ++ return ctx->ops->reqbufs(ctx, rb); ++ ++ return 0; ++} ++ ++static int coda_qbuf(struct file *file, void *priv, ++ struct v4l2_buffer *buf) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ ++ if (ctx->inst_type == CODA_INST_DECODER && ++ buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ buf->flags &= ~V4L2_BUF_FLAG_LAST; ++ ++ return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf); ++} ++ ++static int coda_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(priv); ++ int ret; ++ ++ ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf); ++ ++ if (ctx->inst_type == CODA_INST_DECODER && ++ buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ buf->flags &= ~V4L2_BUF_FLAG_LAST; ++ ++ return ret; ++} ++ ++void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, ++ enum vb2_buffer_state state) ++{ ++ const struct v4l2_event eos_event = { ++ .type = V4L2_EVENT_EOS ++ }; ++ ++ if (buf->flags & V4L2_BUF_FLAG_LAST) ++ v4l2_event_queue_fh(&ctx->fh, &eos_event); ++ ++ v4l2_m2m_buf_done(buf, state); ++} ++ ++static int coda_g_selection(struct file *file, void *fh, ++ struct v4l2_selection *s) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ struct coda_q_data *q_data; ++ struct v4l2_rect r, *rsel; ++ ++ q_data = get_q_data(ctx, s->type); ++ if (!q_data) ++ return -EINVAL; ++ ++ r.left = 0; ++ r.top = 0; ++ r.width = q_data->width; ++ r.height = q_data->height; ++ rsel = &q_data->rect; ++ ++ switch (s->target) { ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ rsel = &r; ++ fallthrough; ++ case V4L2_SEL_TGT_CROP: ++ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || ++ ctx->inst_type == CODA_INST_DECODER) ++ return -EINVAL; ++ break; ++ case V4L2_SEL_TGT_COMPOSE_BOUNDS: ++ case V4L2_SEL_TGT_COMPOSE_PADDED: ++ rsel = &r; ++ fallthrough; ++ case V4L2_SEL_TGT_COMPOSE: ++ case V4L2_SEL_TGT_COMPOSE_DEFAULT: ++ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || ++ ctx->inst_type == CODA_INST_ENCODER) ++ return -EINVAL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ s->r = *rsel; ++ ++ return 0; ++} ++ ++static int coda_s_selection(struct file *file, void *fh, ++ struct v4l2_selection *s) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ struct coda_q_data *q_data; ++ ++ switch (s->target) { ++ case V4L2_SEL_TGT_CROP: ++ if (ctx->inst_type == CODA_INST_ENCODER && ++ s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { ++ q_data = get_q_data(ctx, s->type); ++ if (!q_data) ++ return -EINVAL; ++ ++ s->r.left = 0; ++ s->r.top = 0; ++ s->r.width = clamp(s->r.width, 2U, q_data->width); ++ s->r.height = clamp(s->r.height, 2U, q_data->height); ++ ++ if (s->flags & V4L2_SEL_FLAG_LE) { ++ s->r.width = round_up(s->r.width, 2); ++ s->r.height = round_up(s->r.height, 2); ++ } else { ++ s->r.width = round_down(s->r.width, 2); ++ s->r.height = round_down(s->r.height, 2); ++ } ++ ++ q_data->rect = s->r; ++ ++ coda_dbg(1, ctx, "Setting crop rectangle: %dx%d\n", ++ s->r.width, s->r.height); ++ ++ return 0; ++ } ++ fallthrough; ++ case V4L2_SEL_TGT_NATIVE_SIZE: ++ case V4L2_SEL_TGT_COMPOSE: ++ return coda_g_selection(file, fh, s); ++ default: ++ /* v4l2-compliance expects this to fail for read-only targets */ ++ return -EINVAL; ++ } ++} ++ ++static void coda_wake_up_capture_queue(struct coda_ctx *ctx) ++{ ++ struct vb2_queue *dst_vq; ++ ++ coda_dbg(1, ctx, "waking up capture queue\n"); ++ ++ dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ dst_vq->last_buffer_dequeued = true; ++ wake_up(&dst_vq->done_wq); ++} ++ ++static int coda_encoder_cmd(struct file *file, void *fh, ++ struct v4l2_encoder_cmd *ec) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ struct vb2_v4l2_buffer *buf; ++ int ret; ++ ++ ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec); ++ if (ret < 0) ++ return ret; ++ ++ mutex_lock(&ctx->wakeup_mutex); ++ buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx); ++ if (buf) { ++ /* ++ * If the last output buffer is still on the queue, make sure ++ * that decoder finish_run will see the last flag and report it ++ * to userspace. ++ */ ++ buf->flags |= V4L2_BUF_FLAG_LAST; ++ } else { ++ /* Set the stream-end flag on this context */ ++ ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; ++ ++ /* ++ * If the last output buffer has already been taken from the ++ * queue, wake up the capture queue and signal end of stream ++ * via the -EPIPE mechanism. ++ */ ++ coda_wake_up_capture_queue(ctx); ++ } ++ mutex_unlock(&ctx->wakeup_mutex); ++ ++ return 0; ++} ++ ++static bool coda_mark_last_meta(struct coda_ctx *ctx) ++{ ++ struct coda_buffer_meta *meta; ++ ++ coda_dbg(1, ctx, "marking last meta\n"); ++ ++ spin_lock(&ctx->buffer_meta_lock); ++ if (list_empty(&ctx->buffer_meta_list)) { ++ spin_unlock(&ctx->buffer_meta_lock); ++ return false; ++ } ++ ++ meta = list_last_entry(&ctx->buffer_meta_list, struct coda_buffer_meta, ++ list); ++ meta->last = true; ++ ++ spin_unlock(&ctx->buffer_meta_lock); ++ return true; ++} ++ ++static bool coda_mark_last_dst_buf(struct coda_ctx *ctx) ++{ ++ struct vb2_v4l2_buffer *buf; ++ struct vb2_buffer *dst_vb; ++ struct vb2_queue *dst_vq; ++ unsigned long flags; ++ ++ coda_dbg(1, ctx, "marking last capture buffer\n"); ++ ++ dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ spin_lock_irqsave(&dst_vq->done_lock, flags); ++ if (list_empty(&dst_vq->done_list)) { ++ spin_unlock_irqrestore(&dst_vq->done_lock, flags); ++ return false; ++ } ++ ++ dst_vb = list_last_entry(&dst_vq->done_list, struct vb2_buffer, ++ done_entry); ++ buf = to_vb2_v4l2_buffer(dst_vb); ++ buf->flags |= V4L2_BUF_FLAG_LAST; ++ ++ spin_unlock_irqrestore(&dst_vq->done_lock, flags); ++ return true; ++} ++ ++static int coda_decoder_cmd(struct file *file, void *fh, ++ struct v4l2_decoder_cmd *dc) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ struct coda_dev *dev = ctx->dev; ++ struct vb2_v4l2_buffer *buf; ++ struct vb2_queue *dst_vq; ++ bool stream_end; ++ bool wakeup; ++ int ret; ++ ++ ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc); ++ if (ret < 0) ++ return ret; ++ ++ switch (dc->cmd) { ++ case V4L2_DEC_CMD_START: ++ mutex_lock(&dev->coda_mutex); ++ mutex_lock(&ctx->bitstream_mutex); ++ coda_bitstream_flush(ctx); ++ dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, ++ V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ vb2_clear_last_buffer_dequeued(dst_vq); ++ ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG; ++ coda_fill_bitstream(ctx, NULL); ++ mutex_unlock(&ctx->bitstream_mutex); ++ mutex_unlock(&dev->coda_mutex); ++ break; ++ case V4L2_DEC_CMD_STOP: ++ stream_end = false; ++ wakeup = false; ++ ++ mutex_lock(&ctx->wakeup_mutex); ++ ++ buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx); ++ if (buf) { ++ coda_dbg(1, ctx, "marking last pending buffer\n"); ++ ++ /* Mark last buffer */ ++ buf->flags |= V4L2_BUF_FLAG_LAST; ++ ++ if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0) { ++ coda_dbg(1, ctx, "all remaining buffers queued\n"); ++ stream_end = true; ++ } ++ } else { ++ if (ctx->use_bit) ++ if (coda_mark_last_meta(ctx)) ++ stream_end = true; ++ else ++ wakeup = true; ++ else ++ if (!coda_mark_last_dst_buf(ctx)) ++ wakeup = true; ++ } ++ ++ if (stream_end) { ++ coda_dbg(1, ctx, "all remaining buffers queued\n"); ++ ++ /* Set the stream-end flag on this context */ ++ coda_bit_stream_end_flag(ctx); ++ ctx->hold = false; ++ v4l2_m2m_try_schedule(ctx->fh.m2m_ctx); ++ } ++ ++ if (wakeup) { ++ /* If there is no buffer in flight, wake up */ ++ coda_wake_up_capture_queue(ctx); ++ } ++ ++ mutex_unlock(&ctx->wakeup_mutex); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int coda_enum_framesizes(struct file *file, void *fh, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ struct coda_q_data *q_data_dst; ++ const struct coda_codec *codec; ++ ++ if (fsize->index) ++ return -EINVAL; ++ ++ if (coda_format_normalize_yuv(fsize->pixel_format) == ++ V4L2_PIX_FMT_YUV420) { ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ codec = coda_find_codec(ctx->dev, fsize->pixel_format, ++ q_data_dst->fourcc); ++ } else { ++ codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, ++ fsize->pixel_format); ++ } ++ if (!codec) ++ return -EINVAL; ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; ++ fsize->stepwise.min_width = MIN_W; ++ fsize->stepwise.max_width = codec->max_w; ++ fsize->stepwise.step_width = 1; ++ fsize->stepwise.min_height = MIN_H; ++ fsize->stepwise.max_height = codec->max_h; ++ fsize->stepwise.step_height = 1; ++ ++ return 0; ++} ++ ++static int coda_enum_frameintervals(struct file *file, void *fh, ++ struct v4l2_frmivalenum *f) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ struct coda_q_data *q_data; ++ const struct coda_codec *codec; ++ ++ if (f->index) ++ return -EINVAL; ++ ++ /* Disallow YUYV if the vdoa is not available */ ++ if (!ctx->vdoa && f->pixel_format == V4L2_PIX_FMT_YUYV) ++ return -EINVAL; ++ ++ if (coda_format_normalize_yuv(f->pixel_format) == V4L2_PIX_FMT_YUV420) { ++ q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ codec = coda_find_codec(ctx->dev, f->pixel_format, ++ q_data->fourcc); ++ } else { ++ codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, ++ f->pixel_format); ++ } ++ if (!codec) ++ return -EINVAL; ++ ++ if (f->width < MIN_W || f->width > codec->max_w || ++ f->height < MIN_H || f->height > codec->max_h) ++ return -EINVAL; ++ ++ f->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; ++ f->stepwise.min.numerator = 1; ++ f->stepwise.min.denominator = 65535; ++ f->stepwise.max.numerator = 65536; ++ f->stepwise.max.denominator = 1; ++ f->stepwise.step.numerator = 1; ++ f->stepwise.step.denominator = 1; ++ ++ return 0; ++} ++ ++static int coda_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ struct v4l2_fract *tpf; ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ ++ a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; ++ tpf = &a->parm.output.timeperframe; ++ tpf->denominator = ctx->params.framerate & CODA_FRATE_RES_MASK; ++ tpf->numerator = 1 + (ctx->params.framerate >> ++ CODA_FRATE_DIV_OFFSET); ++ ++ return 0; ++} ++ ++/* ++ * Approximate timeperframe v4l2_fract with values that can be written ++ * into the 16-bit CODA_FRATE_DIV and CODA_FRATE_RES fields. ++ */ ++static void coda_approximate_timeperframe(struct v4l2_fract *timeperframe) ++{ ++ struct v4l2_fract s = *timeperframe; ++ struct v4l2_fract f0; ++ struct v4l2_fract f1 = { 1, 0 }; ++ struct v4l2_fract f2 = { 0, 1 }; ++ unsigned int i, div, s_denominator; ++ ++ /* Lower bound is 1/65535 */ ++ if (s.numerator == 0 || s.denominator / s.numerator > 65535) { ++ timeperframe->numerator = 1; ++ timeperframe->denominator = 65535; ++ return; ++ } ++ ++ /* Upper bound is 65536/1 */ ++ if (s.denominator == 0 || s.numerator / s.denominator > 65536) { ++ timeperframe->numerator = 65536; ++ timeperframe->denominator = 1; ++ return; ++ } ++ ++ /* Reduce fraction to lowest terms */ ++ div = gcd(s.numerator, s.denominator); ++ if (div > 1) { ++ s.numerator /= div; ++ s.denominator /= div; ++ } ++ ++ if (s.numerator <= 65536 && s.denominator < 65536) { ++ *timeperframe = s; ++ return; ++ } ++ ++ /* Find successive convergents from continued fraction expansion */ ++ while (f2.numerator <= 65536 && f2.denominator < 65536) { ++ f0 = f1; ++ f1 = f2; ++ ++ /* Stop when f2 exactly equals timeperframe */ ++ if (s.numerator == 0) ++ break; ++ ++ i = s.denominator / s.numerator; ++ ++ f2.numerator = f0.numerator + i * f1.numerator; ++ f2.denominator = f0.denominator + i * f2.denominator; ++ ++ s_denominator = s.numerator; ++ s.numerator = s.denominator % s.numerator; ++ s.denominator = s_denominator; ++ } ++ ++ *timeperframe = f1; ++} ++ ++static uint32_t coda_timeperframe_to_frate(struct v4l2_fract *timeperframe) ++{ ++ return ((timeperframe->numerator - 1) << CODA_FRATE_DIV_OFFSET) | ++ timeperframe->denominator; ++} ++ ++static int coda_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ struct v4l2_fract *tpf; ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ ++ a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; ++ tpf = &a->parm.output.timeperframe; ++ coda_approximate_timeperframe(tpf); ++ ctx->params.framerate = coda_timeperframe_to_frate(tpf); ++ ctx->params.framerate_changed = true; ++ ++ return 0; ++} ++ ++static int coda_subscribe_event(struct v4l2_fh *fh, ++ const struct v4l2_event_subscription *sub) ++{ ++ struct coda_ctx *ctx = fh_to_ctx(fh); ++ ++ switch (sub->type) { ++ case V4L2_EVENT_EOS: ++ return v4l2_event_subscribe(fh, sub, 0, NULL); ++ case V4L2_EVENT_SOURCE_CHANGE: ++ if (ctx->inst_type == CODA_INST_DECODER) ++ return v4l2_event_subscribe(fh, sub, 0, NULL); ++ else ++ return -EINVAL; ++ default: ++ return v4l2_ctrl_subscribe_event(fh, sub); ++ } ++} ++ ++static const struct v4l2_ioctl_ops coda_ioctl_ops = { ++ .vidioc_querycap = coda_querycap, ++ ++ .vidioc_enum_fmt_vid_cap = coda_enum_fmt, ++ .vidioc_g_fmt_vid_cap = coda_g_fmt, ++ .vidioc_try_fmt_vid_cap = coda_try_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap = coda_s_fmt_vid_cap, ++ ++ .vidioc_enum_fmt_vid_out = coda_enum_fmt, ++ .vidioc_g_fmt_vid_out = coda_g_fmt, ++ .vidioc_try_fmt_vid_out = coda_try_fmt_vid_out, ++ .vidioc_s_fmt_vid_out = coda_s_fmt_vid_out, ++ ++ .vidioc_reqbufs = coda_reqbufs, ++ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, ++ ++ .vidioc_qbuf = coda_qbuf, ++ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, ++ .vidioc_dqbuf = coda_dqbuf, ++ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, ++ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, ++ ++ .vidioc_streamon = v4l2_m2m_ioctl_streamon, ++ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, ++ ++ .vidioc_g_selection = coda_g_selection, ++ .vidioc_s_selection = coda_s_selection, ++ ++ .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, ++ .vidioc_encoder_cmd = coda_encoder_cmd, ++ .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, ++ .vidioc_decoder_cmd = coda_decoder_cmd, ++ ++ .vidioc_g_parm = coda_g_parm, ++ .vidioc_s_parm = coda_s_parm, ++ ++ .vidioc_enum_framesizes = coda_enum_framesizes, ++ .vidioc_enum_frameintervals = coda_enum_frameintervals, ++ ++ .vidioc_subscribe_event = coda_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++/* ++ * Mem-to-mem operations. ++ */ ++ ++static void coda_device_run(void *m2m_priv) ++{ ++ struct coda_ctx *ctx = m2m_priv; ++ struct coda_dev *dev = ctx->dev; ++ ++ queue_work(dev->workqueue, &ctx->pic_run_work); ++} ++ ++static void coda_pic_run_work(struct work_struct *work) ++{ ++ struct coda_ctx *ctx = container_of(work, struct coda_ctx, pic_run_work); ++ struct coda_dev *dev = ctx->dev; ++ int ret; ++ ++ mutex_lock(&ctx->buffer_mutex); ++ mutex_lock(&dev->coda_mutex); ++ ++ ret = ctx->ops->prepare_run(ctx); ++ if (ret < 0 && ctx->inst_type == CODA_INST_DECODER) ++ goto out; ++ ++ if (!wait_for_completion_timeout(&ctx->completion, ++ msecs_to_jiffies(1000))) { ++ if (ctx->use_bit) { ++ dev_err(dev->dev, "CODA PIC_RUN timeout\n"); ++ ++ ctx->hold = true; ++ ++ coda_hw_reset(ctx); ++ } ++ ++ if (ctx->ops->run_timeout) ++ ctx->ops->run_timeout(ctx); ++ } else { ++ ctx->ops->finish_run(ctx); ++ } ++ ++ if ((ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) && ++ ctx->ops->seq_end_work) ++ queue_work(dev->workqueue, &ctx->seq_end_work); ++ ++out: ++ mutex_unlock(&dev->coda_mutex); ++ mutex_unlock(&ctx->buffer_mutex); ++ ++ v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); ++} ++ ++static int coda_job_ready(void *m2m_priv) ++{ ++ struct coda_ctx *ctx = m2m_priv; ++ int src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx); ++ ++ /* ++ * For both 'P' and 'key' frame cases 1 picture ++ * and 1 frame are needed. In the decoder case, ++ * the compressed frame can be in the bitstream. ++ */ ++ if (!src_bufs && ctx->inst_type != CODA_INST_DECODER) { ++ coda_dbg(1, ctx, "not ready: not enough vid-out buffers.\n"); ++ return 0; ++ } ++ ++ if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) { ++ coda_dbg(1, ctx, "not ready: not enough vid-cap buffers.\n"); ++ return 0; ++ } ++ ++ if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) { ++ bool stream_end = ctx->bit_stream_param & ++ CODA_BIT_STREAM_END_FLAG; ++ int num_metas = ctx->num_metas; ++ struct coda_buffer_meta *meta; ++ unsigned int count; ++ ++ count = hweight32(ctx->frm_dis_flg); ++ if (ctx->use_vdoa && count >= (ctx->num_internal_frames - 1)) { ++ coda_dbg(1, ctx, ++ "not ready: all internal buffers in use: %d/%d (0x%x)", ++ count, ctx->num_internal_frames, ++ ctx->frm_dis_flg); ++ return 0; ++ } ++ ++ if (ctx->hold && !src_bufs) { ++ coda_dbg(1, ctx, ++ "not ready: on hold for more buffers.\n"); ++ return 0; ++ } ++ ++ if (!stream_end && (num_metas + src_bufs) < 2) { ++ coda_dbg(1, ctx, ++ "not ready: need 2 buffers available (queue:%d + bitstream:%d)\n", ++ num_metas, src_bufs); ++ return 0; ++ } ++ ++ meta = list_first_entry(&ctx->buffer_meta_list, ++ struct coda_buffer_meta, list); ++ if (!coda_bitstream_can_fetch_past(ctx, meta->end) && ++ !stream_end) { ++ coda_dbg(1, ctx, ++ "not ready: not enough bitstream data to read past %u (%u)\n", ++ meta->end, ctx->bitstream_fifo.kfifo.in); ++ return 0; ++ } ++ } ++ ++ if (ctx->aborting) { ++ coda_dbg(1, ctx, "not ready: aborting\n"); ++ return 0; ++ } ++ ++ coda_dbg(2, ctx, "job ready\n"); ++ ++ return 1; ++} ++ ++static void coda_job_abort(void *priv) ++{ ++ struct coda_ctx *ctx = priv; ++ ++ ctx->aborting = 1; ++ ++ coda_dbg(1, ctx, "job abort\n"); ++} ++ ++static const struct v4l2_m2m_ops coda_m2m_ops = { ++ .device_run = coda_device_run, ++ .job_ready = coda_job_ready, ++ .job_abort = coda_job_abort, ++}; ++ ++static void set_default_params(struct coda_ctx *ctx) ++{ ++ unsigned int max_w, max_h, usize, csize; ++ ++ ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0], ++ ctx->cvd->dst_formats[0]); ++ max_w = min(ctx->codec->max_w, 1920U); ++ max_h = min(ctx->codec->max_h, 1088U); ++ usize = max_w * max_h * 3 / 2; ++ csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h); ++ ++ ctx->params.codec_mode = ctx->codec->mode; ++ if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_JPEG || ++ ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG) { ++ ctx->colorspace = V4L2_COLORSPACE_SRGB; ++ ctx->xfer_func = V4L2_XFER_FUNC_SRGB; ++ ctx->ycbcr_enc = V4L2_YCBCR_ENC_601; ++ ctx->quantization = V4L2_QUANTIZATION_FULL_RANGE; ++ } else { ++ ctx->colorspace = V4L2_COLORSPACE_REC709; ++ ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; ++ ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; ++ ctx->quantization = V4L2_QUANTIZATION_DEFAULT; ++ } ++ ctx->params.framerate = 30; ++ ++ /* Default formats for output and input queues */ ++ ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->cvd->src_formats[0]; ++ ctx->q_data[V4L2_M2M_DST].fourcc = ctx->cvd->dst_formats[0]; ++ ctx->q_data[V4L2_M2M_SRC].width = max_w; ++ ctx->q_data[V4L2_M2M_SRC].height = max_h; ++ ctx->q_data[V4L2_M2M_DST].width = max_w; ++ ctx->q_data[V4L2_M2M_DST].height = max_h; ++ if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) { ++ ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w; ++ ctx->q_data[V4L2_M2M_SRC].sizeimage = usize; ++ ctx->q_data[V4L2_M2M_DST].bytesperline = 0; ++ ctx->q_data[V4L2_M2M_DST].sizeimage = csize; ++ } else { ++ ctx->q_data[V4L2_M2M_SRC].bytesperline = 0; ++ ctx->q_data[V4L2_M2M_SRC].sizeimage = csize; ++ ctx->q_data[V4L2_M2M_DST].bytesperline = max_w; ++ ctx->q_data[V4L2_M2M_DST].sizeimage = usize; ++ } ++ ctx->q_data[V4L2_M2M_SRC].rect.width = max_w; ++ ctx->q_data[V4L2_M2M_SRC].rect.height = max_h; ++ ctx->q_data[V4L2_M2M_DST].rect.width = max_w; ++ ctx->q_data[V4L2_M2M_DST].rect.height = max_h; ++ ++ /* ++ * Since the RBC2AXI logic only supports a single chroma plane, ++ * macroblock tiling only works for to NV12 pixel format. ++ */ ++ ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP; ++} ++ ++/* ++ * Queue operations ++ */ ++static int coda_queue_setup(struct vb2_queue *vq, ++ unsigned int *nbuffers, unsigned int *nplanes, ++ unsigned int sizes[], struct device *alloc_devs[]) ++{ ++ struct coda_ctx *ctx = vb2_get_drv_priv(vq); ++ struct coda_q_data *q_data; ++ unsigned int size; ++ ++ q_data = get_q_data(ctx, vq->type); ++ size = q_data->sizeimage; ++ ++ if (*nplanes) ++ return sizes[0] < size ? -EINVAL : 0; ++ ++ *nplanes = 1; ++ sizes[0] = size; ++ ++ coda_dbg(1, ctx, "get %d buffer(s) of size %d each.\n", *nbuffers, ++ size); ++ ++ return 0; ++} ++ ++static int coda_buf_prepare(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ struct coda_q_data *q_data; ++ ++ q_data = get_q_data(ctx, vb->vb2_queue->type); ++ if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { ++ if (vbuf->field == V4L2_FIELD_ANY) ++ vbuf->field = V4L2_FIELD_NONE; ++ if (vbuf->field != V4L2_FIELD_NONE) { ++ v4l2_warn(&ctx->dev->v4l2_dev, ++ "%s field isn't supported\n", __func__); ++ return -EINVAL; ++ } ++ } ++ ++ if (vb2_plane_size(vb, 0) < q_data->sizeimage) { ++ v4l2_warn(&ctx->dev->v4l2_dev, ++ "%s data will not fit into plane (%lu < %lu)\n", ++ __func__, vb2_plane_size(vb, 0), ++ (long)q_data->sizeimage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void coda_update_menu_ctrl(struct v4l2_ctrl *ctrl, int value) ++{ ++ if (!ctrl) ++ return; ++ ++ v4l2_ctrl_lock(ctrl); ++ ++ /* ++ * Extend the control range if the parsed stream contains a known but ++ * unsupported value or level. ++ */ ++ if (value > ctrl->maximum) { ++ __v4l2_ctrl_modify_range(ctrl, ctrl->minimum, value, ++ ctrl->menu_skip_mask & ~(1 << value), ++ ctrl->default_value); ++ } else if (value < ctrl->minimum) { ++ __v4l2_ctrl_modify_range(ctrl, value, ctrl->maximum, ++ ctrl->menu_skip_mask & ~(1 << value), ++ ctrl->default_value); ++ } ++ ++ __v4l2_ctrl_s_ctrl(ctrl, value); ++ ++ v4l2_ctrl_unlock(ctrl); ++} ++ ++void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc, ++ u8 level_idc) ++{ ++ const char * const *profile_names; ++ const char * const *level_names; ++ struct v4l2_ctrl *profile_ctrl; ++ struct v4l2_ctrl *level_ctrl; ++ const char *codec_name; ++ u32 profile_cid; ++ u32 level_cid; ++ int profile; ++ int level; ++ ++ switch (ctx->codec->src_fourcc) { ++ case V4L2_PIX_FMT_H264: ++ codec_name = "H264"; ++ profile_cid = V4L2_CID_MPEG_VIDEO_H264_PROFILE; ++ level_cid = V4L2_CID_MPEG_VIDEO_H264_LEVEL; ++ profile_ctrl = ctx->h264_profile_ctrl; ++ level_ctrl = ctx->h264_level_ctrl; ++ profile = coda_h264_profile(profile_idc); ++ level = coda_h264_level(level_idc); ++ break; ++ case V4L2_PIX_FMT_MPEG2: ++ codec_name = "MPEG-2"; ++ profile_cid = V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE; ++ level_cid = V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL; ++ profile_ctrl = ctx->mpeg2_profile_ctrl; ++ level_ctrl = ctx->mpeg2_level_ctrl; ++ profile = coda_mpeg2_profile(profile_idc); ++ level = coda_mpeg2_level(level_idc); ++ break; ++ case V4L2_PIX_FMT_MPEG4: ++ codec_name = "MPEG-4"; ++ profile_cid = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE; ++ level_cid = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL; ++ profile_ctrl = ctx->mpeg4_profile_ctrl; ++ level_ctrl = ctx->mpeg4_level_ctrl; ++ profile = coda_mpeg4_profile(profile_idc); ++ level = coda_mpeg4_level(level_idc); ++ break; ++ default: ++ return; ++ } ++ ++ profile_names = v4l2_ctrl_get_menu(profile_cid); ++ level_names = v4l2_ctrl_get_menu(level_cid); ++ ++ if (profile < 0) { ++ v4l2_warn(&ctx->dev->v4l2_dev, "Invalid %s profile: %u\n", ++ codec_name, profile_idc); ++ } else { ++ coda_dbg(1, ctx, "Parsed %s profile: %s\n", codec_name, ++ profile_names[profile]); ++ coda_update_menu_ctrl(profile_ctrl, profile); ++ } ++ ++ if (level < 0) { ++ v4l2_warn(&ctx->dev->v4l2_dev, "Invalid %s level: %u\n", ++ codec_name, level_idc); ++ } else { ++ coda_dbg(1, ctx, "Parsed %s level: %s\n", codec_name, ++ level_names[level]); ++ coda_update_menu_ctrl(level_ctrl, level); ++ } ++} ++ ++static void coda_queue_source_change_event(struct coda_ctx *ctx) ++{ ++ static const struct v4l2_event source_change_event = { ++ .type = V4L2_EVENT_SOURCE_CHANGE, ++ .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, ++ }; ++ ++ v4l2_event_queue_fh(&ctx->fh, &source_change_event); ++} ++ ++static void coda_buf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); ++ struct vb2_queue *vq = vb->vb2_queue; ++ struct coda_q_data *q_data; ++ ++ q_data = get_q_data(ctx, vb->vb2_queue->type); ++ ++ /* ++ * In the decoder case, immediately try to copy the buffer into the ++ * bitstream ringbuffer and mark it as ready to be dequeued. ++ */ ++ if (ctx->bitstream.size && vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { ++ /* ++ * For backwards compatibility, queuing an empty buffer marks ++ * the stream end ++ */ ++ if (vb2_get_plane_payload(vb, 0) == 0) ++ coda_bit_stream_end_flag(ctx); ++ ++ if (q_data->fourcc == V4L2_PIX_FMT_H264) { ++ /* ++ * Unless already done, try to obtain profile_idc and ++ * level_idc from the SPS header. This allows to decide ++ * whether to enable reordering during sequence ++ * initialization. ++ */ ++ if (!ctx->params.h264_profile_idc) { ++ coda_sps_parse_profile(ctx, vb); ++ coda_update_profile_level_ctrls(ctx, ++ ctx->params.h264_profile_idc, ++ ctx->params.h264_level_idc); ++ } ++ } ++ ++ mutex_lock(&ctx->bitstream_mutex); ++ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); ++ if (vb2_is_streaming(vb->vb2_queue)) ++ /* This set buf->sequence = ctx->qsequence++ */ ++ coda_fill_bitstream(ctx, NULL); ++ mutex_unlock(&ctx->bitstream_mutex); ++ ++ if (!ctx->initialized) { ++ /* ++ * Run sequence initialization in case the queued ++ * buffer contained headers. ++ */ ++ if (vb2_is_streaming(vb->vb2_queue) && ++ ctx->ops->seq_init_work) { ++ queue_work(ctx->dev->workqueue, ++ &ctx->seq_init_work); ++ flush_work(&ctx->seq_init_work); ++ } ++ ++ if (ctx->initialized) ++ coda_queue_source_change_event(ctx); ++ } ++ } else { ++ if ((ctx->inst_type == CODA_INST_ENCODER || !ctx->use_bit) && ++ vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ vbuf->sequence = ctx->qsequence++; ++ v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); ++ } ++} ++ ++int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf, ++ size_t size, const char *name, struct dentry *parent) ++{ ++ buf->vaddr = dma_alloc_coherent(dev->dev, size, &buf->paddr, ++ GFP_KERNEL); ++ if (!buf->vaddr) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed to allocate %s buffer of size %zu\n", ++ name, size); ++ return -ENOMEM; ++ } ++ ++ buf->size = size; ++ ++ if (name && parent) { ++ buf->blob.data = buf->vaddr; ++ buf->blob.size = size; ++ buf->dentry = debugfs_create_blob(name, 0444, parent, ++ &buf->blob); ++ } ++ ++ return 0; ++} ++ ++void coda_free_aux_buf(struct coda_dev *dev, ++ struct coda_aux_buf *buf) ++{ ++ if (buf->vaddr) { ++ dma_free_coherent(dev->dev, buf->size, buf->vaddr, buf->paddr); ++ buf->vaddr = NULL; ++ buf->size = 0; ++ debugfs_remove(buf->dentry); ++ buf->dentry = NULL; ++ } ++} ++ ++static int coda_start_streaming(struct vb2_queue *q, unsigned int count) ++{ ++ struct coda_ctx *ctx = vb2_get_drv_priv(q); ++ struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev; ++ struct coda_q_data *q_data_src, *q_data_dst; ++ struct v4l2_m2m_buffer *m2m_buf, *tmp; ++ struct vb2_v4l2_buffer *buf; ++ struct list_head list; ++ int ret = 0; ++ ++ if (count < 1) ++ return -EINVAL; ++ ++ coda_dbg(1, ctx, "start streaming %s\n", v4l2_type_names[q->type]); ++ ++ INIT_LIST_HEAD(&list); ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { ++ if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) { ++ /* copy the buffers that were queued before streamon */ ++ mutex_lock(&ctx->bitstream_mutex); ++ coda_fill_bitstream(ctx, &list); ++ mutex_unlock(&ctx->bitstream_mutex); ++ ++ if (ctx->dev->devtype->product != CODA_960 && ++ coda_get_bitstream_payload(ctx) < 512) { ++ v4l2_err(v4l2_dev, "start payload < 512\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ if (!ctx->initialized) { ++ /* Run sequence initialization */ ++ if (ctx->ops->seq_init_work) { ++ queue_work(ctx->dev->workqueue, ++ &ctx->seq_init_work); ++ flush_work(&ctx->seq_init_work); ++ } ++ } ++ } ++ ++ /* ++ * Check the first input JPEG buffer to determine chroma ++ * subsampling. ++ */ ++ if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) { ++ buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); ++ coda_jpeg_decode_header(ctx, &buf->vb2_buf); ++ /* ++ * We have to start streaming even if the first buffer ++ * does not contain a valid JPEG image. The error will ++ * be caught during device run and will be signalled ++ * via the capture buffer error flag. ++ */ ++ ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ q_data_dst->width = round_up(q_data_src->width, 16); ++ q_data_dst->height = round_up(q_data_src->height, 16); ++ q_data_dst->bytesperline = q_data_dst->width; ++ if (ctx->params.jpeg_chroma_subsampling == ++ V4L2_JPEG_CHROMA_SUBSAMPLING_420) { ++ q_data_dst->sizeimage = ++ q_data_dst->bytesperline * ++ q_data_dst->height * 3 / 2; ++ if (q_data_dst->fourcc != V4L2_PIX_FMT_YUV420) ++ q_data_dst->fourcc = V4L2_PIX_FMT_NV12; ++ } else { ++ q_data_dst->sizeimage = ++ q_data_dst->bytesperline * ++ q_data_dst->height * 2; ++ q_data_dst->fourcc = V4L2_PIX_FMT_YUV422P; ++ } ++ q_data_dst->rect.left = 0; ++ q_data_dst->rect.top = 0; ++ q_data_dst->rect.width = q_data_src->width; ++ q_data_dst->rect.height = q_data_src->height; ++ } ++ ctx->streamon_out = 1; ++ } else { ++ ctx->streamon_cap = 1; ++ } ++ ++ /* Don't start the coda unless both queues are on */ ++ if (!(ctx->streamon_out && ctx->streamon_cap)) ++ goto out; ++ ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ if ((q_data_src->rect.width != q_data_dst->width && ++ round_up(q_data_src->rect.width, 16) != q_data_dst->width) || ++ (q_data_src->rect.height != q_data_dst->height && ++ round_up(q_data_src->rect.height, 16) != q_data_dst->height)) { ++ v4l2_err(v4l2_dev, "can't convert %dx%d to %dx%d\n", ++ q_data_src->rect.width, q_data_src->rect.height, ++ q_data_dst->width, q_data_dst->height); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ /* Allow BIT decoder device_run with no new buffers queued */ ++ if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) ++ v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true); ++ ++ ctx->gopcounter = ctx->params.gop_size - 1; ++ ++ if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG) ++ ctx->params.gop_size = 1; ++ ctx->gopcounter = ctx->params.gop_size - 1; ++ /* Only decoders have this control */ ++ if (ctx->mb_err_cnt_ctrl) ++ v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, 0); ++ ++ ret = ctx->ops->start_streaming(ctx); ++ if (ctx->inst_type == CODA_INST_DECODER) { ++ if (ret == -EAGAIN) ++ goto out; ++ } ++ if (ret < 0) ++ goto err; ++ ++out: ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { ++ list_for_each_entry_safe(m2m_buf, tmp, &list, list) { ++ list_del(&m2m_buf->list); ++ v4l2_m2m_buf_done(&m2m_buf->vb, VB2_BUF_STATE_DONE); ++ } ++ } ++ return 0; ++ ++err: ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { ++ list_for_each_entry_safe(m2m_buf, tmp, &list, list) { ++ list_del(&m2m_buf->list); ++ v4l2_m2m_buf_done(&m2m_buf->vb, VB2_BUF_STATE_QUEUED); ++ } ++ while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) ++ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED); ++ } else { ++ while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) ++ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED); ++ } ++ return ret; ++} ++ ++static void coda_stop_streaming(struct vb2_queue *q) ++{ ++ struct coda_ctx *ctx = vb2_get_drv_priv(q); ++ struct coda_dev *dev = ctx->dev; ++ struct vb2_v4l2_buffer *buf; ++ bool stop; ++ ++ stop = ctx->streamon_out && ctx->streamon_cap; ++ ++ coda_dbg(1, ctx, "stop streaming %s\n", v4l2_type_names[q->type]); ++ ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { ++ ctx->streamon_out = 0; ++ ++ coda_bit_stream_end_flag(ctx); ++ ++ ctx->qsequence = 0; ++ ++ while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) ++ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); ++ } else { ++ ctx->streamon_cap = 0; ++ ++ ctx->osequence = 0; ++ ctx->sequence_offset = 0; ++ ++ while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) ++ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); ++ } ++ ++ if (stop) { ++ struct coda_buffer_meta *meta; ++ ++ if (ctx->ops->seq_end_work) { ++ queue_work(dev->workqueue, &ctx->seq_end_work); ++ flush_work(&ctx->seq_end_work); ++ } ++ spin_lock(&ctx->buffer_meta_lock); ++ while (!list_empty(&ctx->buffer_meta_list)) { ++ meta = list_first_entry(&ctx->buffer_meta_list, ++ struct coda_buffer_meta, list); ++ list_del(&meta->list); ++ kfree(meta); ++ } ++ ctx->num_metas = 0; ++ spin_unlock(&ctx->buffer_meta_lock); ++ kfifo_init(&ctx->bitstream_fifo, ++ ctx->bitstream.vaddr, ctx->bitstream.size); ++ ctx->runcounter = 0; ++ ctx->aborting = 0; ++ ctx->hold = false; ++ } ++ ++ if (!ctx->streamon_out && !ctx->streamon_cap) ++ ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG; ++} ++ ++static const struct vb2_ops coda_qops = { ++ .queue_setup = coda_queue_setup, ++ .buf_prepare = coda_buf_prepare, ++ .buf_queue = coda_buf_queue, ++ .start_streaming = coda_start_streaming, ++ .stop_streaming = coda_stop_streaming, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++}; ++ ++static int coda_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ const char * const *val_names = v4l2_ctrl_get_menu(ctrl->id); ++ struct coda_ctx *ctx = ++ container_of(ctrl->handler, struct coda_ctx, ctrls); ++ ++ if (val_names) ++ coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d (\"%s\")\n", ++ ctrl->id, ctrl->name, ctrl->val, val_names[ctrl->val]); ++ else ++ coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d\n", ++ ctrl->id, ctrl->name, ctrl->val); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_HFLIP: ++ if (ctrl->val) ++ ctx->params.rot_mode |= CODA_MIR_HOR; ++ else ++ ctx->params.rot_mode &= ~CODA_MIR_HOR; ++ break; ++ case V4L2_CID_VFLIP: ++ if (ctrl->val) ++ ctx->params.rot_mode |= CODA_MIR_VER; ++ else ++ ctx->params.rot_mode &= ~CODA_MIR_VER; ++ break; ++ case V4L2_CID_MPEG_VIDEO_BITRATE: ++ ctx->params.bitrate = ctrl->val / 1000; ++ ctx->params.bitrate_changed = true; ++ break; ++ case V4L2_CID_MPEG_VIDEO_GOP_SIZE: ++ ctx->params.gop_size = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: ++ ctx->params.h264_intra_qp = ctrl->val; ++ ctx->params.h264_intra_qp_changed = true; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: ++ ctx->params.h264_inter_qp = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: ++ ctx->params.h264_min_qp = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: ++ ctx->params.h264_max_qp = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: ++ ctx->params.h264_slice_alpha_c0_offset_div2 = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: ++ ctx->params.h264_slice_beta_offset_div2 = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: ++ ctx->params.h264_disable_deblocking_filter_idc = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION: ++ ctx->params.h264_constrained_intra_pred_flag = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: ++ ctx->params.frame_rc_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: ++ ctx->params.mb_rc_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET: ++ ctx->params.h264_chroma_qp_index_offset = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_PROFILE: ++ /* TODO: switch between baseline and constrained baseline */ ++ if (ctx->inst_type == CODA_INST_ENCODER) ++ ctx->params.h264_profile_idc = 66; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_LEVEL: ++ /* nothing to do, this is set by the encoder */ ++ break; ++ case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: ++ ctx->params.mpeg4_intra_qp = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: ++ ctx->params.mpeg4_inter_qp = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: ++ case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: ++ case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: ++ case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: ++ /* nothing to do, these are fixed */ ++ break; ++ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: ++ ctx->params.slice_mode = ctrl->val; ++ ctx->params.slice_mode_changed = true; ++ break; ++ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: ++ ctx->params.slice_max_mb = ctrl->val; ++ ctx->params.slice_mode_changed = true; ++ break; ++ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: ++ ctx->params.slice_max_bits = ctrl->val * 8; ++ ctx->params.slice_mode_changed = true; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEADER_MODE: ++ break; ++ case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: ++ ctx->params.intra_refresh = ctrl->val; ++ ctx->params.intra_refresh_changed = true; ++ break; ++ case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: ++ ctx->params.force_ipicture = true; ++ break; ++ case V4L2_CID_JPEG_COMPRESSION_QUALITY: ++ coda_set_jpeg_compression_quality(ctx, ctrl->val); ++ break; ++ case V4L2_CID_JPEG_RESTART_INTERVAL: ++ ctx->params.jpeg_restart_interval = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_VBV_DELAY: ++ ctx->params.vbv_delay = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_VBV_SIZE: ++ ctx->params.vbv_size = min(ctrl->val * 8192, 0x7fffffff); ++ break; ++ default: ++ coda_dbg(1, ctx, "Invalid control, id=%d, val=%d\n", ++ ctrl->id, ctrl->val); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops coda_ctrl_ops = { ++ .s_ctrl = coda_s_ctrl, ++}; ++ ++static void coda_encode_ctrls(struct coda_ctx *ctx) ++{ ++ int max_gop_size = (ctx->dev->devtype->product == CODA_DX6) ? 60 : 99; ++ ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1000, 0); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, max_gop_size, 1, 16); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25); ++ if (ctx->dev->devtype->product != CODA_960) { ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 51, 1, 12); ++ } ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, -6, 6, 1, 0); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0); ++ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, ++ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY, ++ 0x0, V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION, 0, 1, 1, ++ 0); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, 0, 1, 1, 1); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, -12, 12, 1, 0); ++ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_PROFILE, ++ V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, 0x0, ++ V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE); ++ if (ctx->dev->devtype->product == CODA_HX4 || ++ ctx->dev->devtype->product == CODA_7541) { ++ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LEVEL, ++ V4L2_MPEG_VIDEO_H264_LEVEL_3_1, ++ ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1)), ++ V4L2_MPEG_VIDEO_H264_LEVEL_3_1); ++ } ++ if (ctx->dev->devtype->product == CODA_960) { ++ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LEVEL, ++ V4L2_MPEG_VIDEO_H264_LEVEL_4_2, ++ ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | ++ (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2)), ++ V4L2_MPEG_VIDEO_H264_LEVEL_4_0); ++ } ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, 1, 31, 1, 2); ++ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, ++ V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE, 0x0, ++ V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE); ++ if (ctx->dev->devtype->product == CODA_HX4 || ++ ctx->dev->devtype->product == CODA_7541 || ++ ctx->dev->devtype->product == CODA_960) { ++ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, ++ V4L2_MPEG_VIDEO_MPEG4_LEVEL_5, ++ ~(1 << V4L2_MPEG_VIDEO_MPEG4_LEVEL_5), ++ V4L2_MPEG_VIDEO_MPEG4_LEVEL_5); ++ } ++ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, ++ V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES, 0x0, ++ V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, 1, 0x3fffffff, 1, 1); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, 1, 0x3fffffff, 1, ++ 500); ++ v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEADER_MODE, ++ V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, ++ (1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE), ++ V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0, ++ 1920 * 1088 / 256, 1, 0); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_VBV_DELAY, 0, 0x7fff, 1, 0); ++ /* ++ * The maximum VBV size value is 0x7fffffff bits, ++ * one bit less than 262144 KiB ++ */ ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_VBV_SIZE, 0, 262144, 1, 0); ++} ++ ++static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx) ++{ ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_JPEG_COMPRESSION_QUALITY, 5, 100, 1, 50); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_JPEG_RESTART_INTERVAL, 0, 100, 1, 0); ++} ++ ++static void coda_decode_ctrls(struct coda_ctx *ctx) ++{ ++ u8 max; ++ ++ ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, ++ &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE, ++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, ++ ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | ++ (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | ++ (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)), ++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH); ++ if (ctx->h264_profile_ctrl) ++ ctx->h264_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ ++ if (ctx->dev->devtype->product == CODA_HX4 || ++ ctx->dev->devtype->product == CODA_7541) ++ max = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; ++ else if (ctx->dev->devtype->product == CODA_960) ++ max = V4L2_MPEG_VIDEO_H264_LEVEL_4_1; ++ else ++ return; ++ ctx->h264_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, ++ &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL, max, 0, max); ++ if (ctx->h264_level_ctrl) ++ ctx->h264_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ ++ ctx->mpeg2_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, ++ &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE, ++ V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH, 0, ++ V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH); ++ if (ctx->mpeg2_profile_ctrl) ++ ctx->mpeg2_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ ++ ctx->mpeg2_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, ++ &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL, ++ V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH, 0, ++ V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH); ++ if (ctx->mpeg2_level_ctrl) ++ ctx->mpeg2_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ ++ ctx->mpeg4_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, ++ &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, ++ V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY, 0, ++ V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY); ++ if (ctx->mpeg4_profile_ctrl) ++ ctx->mpeg4_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ ++ ctx->mpeg4_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, ++ &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, ++ V4L2_MPEG_VIDEO_MPEG4_LEVEL_5, 0, ++ V4L2_MPEG_VIDEO_MPEG4_LEVEL_5); ++ if (ctx->mpeg4_level_ctrl) ++ ctx->mpeg4_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++} ++ ++static const struct v4l2_ctrl_config coda_mb_err_cnt_ctrl_config = { ++ .id = V4L2_CID_CODA_MB_ERR_CNT, ++ .name = "Macroblocks Error Count", ++ .type = V4L2_CTRL_TYPE_INTEGER, ++ .min = 0, ++ .max = 0x7fffffff, ++ .step = 1, ++}; ++ ++static int coda_ctrls_setup(struct coda_ctx *ctx) ++{ ++ v4l2_ctrl_handler_init(&ctx->ctrls, 2); ++ ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ if (ctx->inst_type == CODA_INST_ENCODER) { ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, ++ 1, 1, 1, 1); ++ if (ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG) ++ coda_jpeg_encode_ctrls(ctx); ++ else ++ coda_encode_ctrls(ctx); ++ } else { ++ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, ++ 1, 1, 1, 1); ++ if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_H264) ++ coda_decode_ctrls(ctx); ++ ++ ctx->mb_err_cnt_ctrl = v4l2_ctrl_new_custom(&ctx->ctrls, ++ &coda_mb_err_cnt_ctrl_config, ++ NULL); ++ if (ctx->mb_err_cnt_ctrl) ++ ctx->mb_err_cnt_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ } ++ ++ if (ctx->ctrls.error) { ++ v4l2_err(&ctx->dev->v4l2_dev, ++ "control initialization error (%d)", ++ ctx->ctrls.error); ++ return -EINVAL; ++ } ++ ++ return v4l2_ctrl_handler_setup(&ctx->ctrls); ++} ++ ++static int coda_queue_init(struct coda_ctx *ctx, struct vb2_queue *vq) ++{ ++ vq->drv_priv = ctx; ++ vq->ops = &coda_qops; ++ vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); ++ vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ vq->lock = &ctx->dev->dev_mutex; ++ /* One way to indicate end-of-stream for coda is to set the ++ * bytesused == 0. However by default videobuf2 handles bytesused ++ * equal to 0 as a special case and changes its value to the size ++ * of the buffer. Set the allow_zero_bytesused flag, so ++ * that videobuf2 will keep the value of bytesused intact. ++ */ ++ vq->allow_zero_bytesused = 1; ++ /* ++ * We might be fine with no buffers on some of the queues, but that ++ * would need to be reflected in job_ready(). Currently we expect all ++ * queues to have at least one buffer queued. ++ */ ++ vq->min_buffers_needed = 1; ++ vq->dev = ctx->dev->dev; ++ ++ return vb2_queue_init(vq); ++} ++ ++int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq) ++{ ++ int ret; ++ ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ src_vq->io_modes = VB2_DMABUF | VB2_MMAP; ++ src_vq->mem_ops = &vb2_dma_contig_memops; ++ ++ ret = coda_queue_init(priv, src_vq); ++ if (ret) ++ return ret; ++ ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ dst_vq->io_modes = VB2_DMABUF | VB2_MMAP; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; ++ ++ return coda_queue_init(priv, dst_vq); ++} ++ ++int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq) ++{ ++ int ret; ++ ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; ++ src_vq->mem_ops = &vb2_vmalloc_memops; ++ ++ ret = coda_queue_init(priv, src_vq); ++ if (ret) ++ return ret; ++ ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ dst_vq->io_modes = VB2_DMABUF | VB2_MMAP; ++ dst_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; ++ ++ return coda_queue_init(priv, dst_vq); ++} ++ ++/* ++ * File operations ++ */ ++ ++static int coda_open(struct file *file) ++{ ++ struct video_device *vdev = video_devdata(file); ++ struct coda_dev *dev = video_get_drvdata(vdev); ++ struct coda_ctx *ctx; ++ unsigned int max = ~0; ++ char *name; ++ int ret; ++ int idx; ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ++ if (dev->devtype->product == CODA_DX6) ++ max = CODADX6_MAX_INSTANCES - 1; ++ idx = ida_alloc_max(&dev->ida, max, GFP_KERNEL); ++ if (idx < 0) { ++ ret = idx; ++ goto err_coda_max; ++ } ++ ++ name = kasprintf(GFP_KERNEL, "context%d", idx); ++ if (!name) { ++ ret = -ENOMEM; ++ goto err_coda_name_init; ++ } ++ ++ ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root); ++ kfree(name); ++ ++ ctx->cvd = to_coda_video_device(vdev); ++ ctx->inst_type = ctx->cvd->type; ++ ctx->ops = ctx->cvd->ops; ++ ctx->use_bit = !ctx->cvd->direct; ++ init_completion(&ctx->completion); ++ INIT_WORK(&ctx->pic_run_work, coda_pic_run_work); ++ if (ctx->ops->seq_init_work) ++ INIT_WORK(&ctx->seq_init_work, ctx->ops->seq_init_work); ++ if (ctx->ops->seq_end_work) ++ INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work); ++ v4l2_fh_init(&ctx->fh, video_devdata(file)); ++ file->private_data = &ctx->fh; ++ v4l2_fh_add(&ctx->fh); ++ ctx->dev = dev; ++ ctx->idx = idx; ++ ++ coda_dbg(1, ctx, "open instance (%p)\n", ctx); ++ ++ switch (dev->devtype->product) { ++ case CODA_960: ++ /* ++ * Enabling the BWB when decoding can hang the firmware with ++ * certain streams. The issue was tracked as ENGR00293425 by ++ * Freescale. As a workaround, disable BWB for all decoders. ++ * The enable_bwb module parameter allows to override this. ++ */ ++ if (enable_bwb || ctx->inst_type == CODA_INST_ENCODER) ++ ctx->frame_mem_ctrl = CODA9_FRAME_ENABLE_BWB; ++ fallthrough; ++ case CODA_HX4: ++ case CODA_7541: ++ ctx->reg_idx = 0; ++ break; ++ default: ++ ctx->reg_idx = idx; ++ } ++ if (ctx->dev->vdoa && !disable_vdoa) { ++ ctx->vdoa = vdoa_context_create(dev->vdoa); ++ if (!ctx->vdoa) ++ v4l2_warn(&dev->v4l2_dev, ++ "Failed to create vdoa context: not using vdoa"); ++ } ++ ctx->use_vdoa = false; ++ ++ /* Power up and upload firmware if necessary */ ++ ret = pm_runtime_resume_and_get(dev->dev); ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, "failed to power up: %d\n", ret); ++ goto err_pm_get; ++ } ++ ++ ret = clk_prepare_enable(dev->clk_per); ++ if (ret) ++ goto err_clk_enable; ++ ++ ret = clk_prepare_enable(dev->clk_ahb); ++ if (ret) ++ goto err_clk_ahb; ++ ++ set_default_params(ctx); ++ ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, ++ ctx->ops->queue_init); ++ if (IS_ERR(ctx->fh.m2m_ctx)) { ++ ret = PTR_ERR(ctx->fh.m2m_ctx); ++ ++ v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", ++ __func__, ret); ++ goto err_ctx_init; ++ } ++ ++ ret = coda_ctrls_setup(ctx); ++ if (ret) { ++ v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); ++ goto err_ctrls_setup; ++ } ++ ++ ctx->fh.ctrl_handler = &ctx->ctrls; ++ ++ mutex_init(&ctx->bitstream_mutex); ++ mutex_init(&ctx->buffer_mutex); ++ mutex_init(&ctx->wakeup_mutex); ++ INIT_LIST_HEAD(&ctx->buffer_meta_list); ++ spin_lock_init(&ctx->buffer_meta_lock); ++ ++ return 0; ++ ++err_ctrls_setup: ++ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); ++err_ctx_init: ++ clk_disable_unprepare(dev->clk_ahb); ++err_clk_ahb: ++ clk_disable_unprepare(dev->clk_per); ++err_clk_enable: ++ pm_runtime_put_sync(dev->dev); ++err_pm_get: ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++err_coda_name_init: ++ ida_free(&dev->ida, ctx->idx); ++err_coda_max: ++ kfree(ctx); ++ return ret; ++} ++ ++static int coda_release(struct file *file) ++{ ++ struct coda_dev *dev = video_drvdata(file); ++ struct coda_ctx *ctx = fh_to_ctx(file->private_data); ++ ++ coda_dbg(1, ctx, "release instance (%p)\n", ctx); ++ ++ if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) ++ coda_bit_stream_end_flag(ctx); ++ ++ /* If this instance is running, call .job_abort and wait for it to end */ ++ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); ++ ++ if (ctx->vdoa) ++ vdoa_context_destroy(ctx->vdoa); ++ ++ /* In case the instance was not running, we still need to call SEQ_END */ ++ if (ctx->ops->seq_end_work) { ++ queue_work(dev->workqueue, &ctx->seq_end_work); ++ flush_work(&ctx->seq_end_work); ++ } ++ ++ if (ctx->dev->devtype->product == CODA_DX6) ++ coda_free_aux_buf(dev, &ctx->workbuf); ++ ++ v4l2_ctrl_handler_free(&ctx->ctrls); ++ clk_disable_unprepare(dev->clk_ahb); ++ clk_disable_unprepare(dev->clk_per); ++ pm_runtime_put_sync(dev->dev); ++ v4l2_fh_del(&ctx->fh); ++ v4l2_fh_exit(&ctx->fh); ++ ida_free(&dev->ida, ctx->idx); ++ if (ctx->ops->release) ++ ctx->ops->release(ctx); ++ debugfs_remove_recursive(ctx->debugfs_entry); ++ kfree(ctx); ++ ++ return 0; ++} ++ ++static const struct v4l2_file_operations coda_fops = { ++ .owner = THIS_MODULE, ++ .open = coda_open, ++ .release = coda_release, ++ .poll = v4l2_m2m_fop_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = v4l2_m2m_fop_mmap, ++}; ++ ++static int coda_hw_init(struct coda_dev *dev) ++{ ++ u32 data; ++ u16 *p; ++ int i, ret; ++ ++ ret = clk_prepare_enable(dev->clk_per); ++ if (ret) ++ goto err_clk_per; ++ ++ ret = clk_prepare_enable(dev->clk_ahb); ++ if (ret) ++ goto err_clk_ahb; ++ ++ reset_control_reset(dev->rstc); ++ ++ /* ++ * Copy the first CODA_ISRAM_SIZE in the internal SRAM. ++ * The 16-bit chars in the code buffer are in memory access ++ * order, re-sort them to CODA order for register download. ++ * Data in this SRAM survives a reboot. ++ */ ++ p = (u16 *)dev->codebuf.vaddr; ++ if (dev->devtype->product == CODA_DX6) { ++ for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) { ++ data = CODA_DOWN_ADDRESS_SET(i) | ++ CODA_DOWN_DATA_SET(p[i ^ 1]); ++ coda_write(dev, data, CODA_REG_BIT_CODE_DOWN); ++ } ++ } else { ++ for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) { ++ data = CODA_DOWN_ADDRESS_SET(i) | ++ CODA_DOWN_DATA_SET(p[round_down(i, 4) + ++ 3 - (i % 4)]); ++ coda_write(dev, data, CODA_REG_BIT_CODE_DOWN); ++ } ++ } ++ ++ /* Clear registers */ ++ for (i = 0; i < 64; i++) ++ coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); ++ ++ /* Tell the BIT where to find everything it needs */ ++ if (dev->devtype->product == CODA_960 || ++ dev->devtype->product == CODA_7541 || ++ dev->devtype->product == CODA_HX4) { ++ coda_write(dev, dev->tempbuf.paddr, ++ CODA_REG_BIT_TEMP_BUF_ADDR); ++ coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); ++ } else { ++ coda_write(dev, dev->workbuf.paddr, ++ CODA_REG_BIT_WORK_BUF_ADDR); ++ } ++ coda_write(dev, dev->codebuf.paddr, ++ CODA_REG_BIT_CODE_BUF_ADDR); ++ coda_write(dev, 0, CODA_REG_BIT_CODE_RUN); ++ ++ /* Set default values */ ++ switch (dev->devtype->product) { ++ case CODA_DX6: ++ coda_write(dev, CODADX6_STREAM_BUF_PIC_FLUSH, ++ CODA_REG_BIT_STREAM_CTRL); ++ break; ++ default: ++ coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH, ++ CODA_REG_BIT_STREAM_CTRL); ++ } ++ if (dev->devtype->product == CODA_960) ++ coda_write(dev, CODA9_FRAME_ENABLE_BWB, ++ CODA_REG_BIT_FRAME_MEM_CTRL); ++ else ++ coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL); ++ ++ if (dev->devtype->product != CODA_DX6) ++ coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE); ++ ++ coda_write(dev, CODA_INT_INTERRUPT_ENABLE, ++ CODA_REG_BIT_INT_ENABLE); ++ ++ /* Reset VPU and start processor */ ++ data = coda_read(dev, CODA_REG_BIT_CODE_RESET); ++ data |= CODA_REG_RESET_ENABLE; ++ coda_write(dev, data, CODA_REG_BIT_CODE_RESET); ++ udelay(10); ++ data &= ~CODA_REG_RESET_ENABLE; ++ coda_write(dev, data, CODA_REG_BIT_CODE_RESET); ++ coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); ++ ++ clk_disable_unprepare(dev->clk_ahb); ++ clk_disable_unprepare(dev->clk_per); ++ ++ return 0; ++ ++err_clk_ahb: ++ clk_disable_unprepare(dev->clk_per); ++err_clk_per: ++ return ret; ++} ++ ++static int coda_register_device(struct coda_dev *dev, int i) ++{ ++ struct video_device *vfd = &dev->vfd[i]; ++ const char *name; ++ int ret; ++ ++ if (i >= dev->devtype->num_vdevs) ++ return -EINVAL; ++ name = dev->devtype->vdevs[i]->name; ++ ++ strscpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name)); ++ vfd->fops = &coda_fops; ++ vfd->ioctl_ops = &coda_ioctl_ops; ++ vfd->release = video_device_release_empty; ++ vfd->lock = &dev->dev_mutex; ++ vfd->v4l2_dev = &dev->v4l2_dev; ++ vfd->vfl_dir = VFL_DIR_M2M; ++ vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; ++ video_set_drvdata(vfd, dev); ++ ++ /* Not applicable, use the selection API instead */ ++ v4l2_disable_ioctl(vfd, VIDIOC_CROPCAP); ++ v4l2_disable_ioctl(vfd, VIDIOC_G_CROP); ++ v4l2_disable_ioctl(vfd, VIDIOC_S_CROP); ++ ++ if (dev->devtype->vdevs[i]->type == CODA_INST_ENCODER) { ++ v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD); ++ v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD); ++ if (dev->devtype->vdevs[i]->dst_formats[0] == V4L2_PIX_FMT_JPEG) { ++ v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS); ++ v4l2_disable_ioctl(vfd, VIDIOC_G_PARM); ++ v4l2_disable_ioctl(vfd, VIDIOC_S_PARM); ++ } ++ } else { ++ v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD); ++ v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD); ++ v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMESIZES); ++ v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS); ++ v4l2_disable_ioctl(vfd, VIDIOC_G_PARM); ++ v4l2_disable_ioctl(vfd, VIDIOC_S_PARM); ++ } ++ ++ ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); ++ if (!ret) ++ v4l2_info(&dev->v4l2_dev, "%s registered as %s\n", ++ name, video_device_node_name(vfd)); ++ return ret; ++} ++ ++static void coda_copy_firmware(struct coda_dev *dev, const u8 * const buf, ++ size_t size) ++{ ++ u32 *src = (u32 *)buf; ++ ++ /* Check if the firmware has a 16-byte Freescale header, skip it */ ++ if (buf[0] == 'M' && buf[1] == 'X') ++ src += 4; ++ /* ++ * Check whether the firmware is in native order or pre-reordered for ++ * memory access. The first instruction opcode always is 0xe40e. ++ */ ++ if (__le16_to_cpup((__le16 *)src) == 0xe40e) { ++ u32 *dst = dev->codebuf.vaddr; ++ int i; ++ ++ /* Firmware in native order, reorder while copying */ ++ if (dev->devtype->product == CODA_DX6) { ++ for (i = 0; i < (size - 16) / 4; i++) ++ dst[i] = (src[i] << 16) | (src[i] >> 16); ++ } else { ++ for (i = 0; i < (size - 16) / 4; i += 2) { ++ dst[i] = (src[i + 1] << 16) | (src[i + 1] >> 16); ++ dst[i + 1] = (src[i] << 16) | (src[i] >> 16); ++ } ++ } ++ } else { ++ /* Copy the already reordered firmware image */ ++ memcpy(dev->codebuf.vaddr, src, size); ++ } ++} ++ ++static void coda_fw_callback(const struct firmware *fw, void *context); ++ ++static int coda_firmware_request(struct coda_dev *dev) ++{ ++ char *fw; ++ ++ if (dev->firmware >= ARRAY_SIZE(dev->devtype->firmware)) ++ return -EINVAL; ++ ++ fw = dev->devtype->firmware[dev->firmware]; ++ ++ dev_dbg(dev->dev, "requesting firmware '%s' for %s\n", fw, ++ coda_product_name(dev->devtype->product)); ++ ++ return request_firmware_nowait(THIS_MODULE, true, fw, dev->dev, ++ GFP_KERNEL, dev, coda_fw_callback); ++} ++ ++static void coda_fw_callback(const struct firmware *fw, void *context) ++{ ++ struct coda_dev *dev = context; ++ int i, ret; ++ ++ if (!fw) { ++ dev->firmware++; ++ ret = coda_firmware_request(dev); ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, "firmware request failed\n"); ++ goto put_pm; ++ } ++ return; ++ } ++ if (dev->firmware > 0) { ++ /* ++ * Since we can't suppress warnings for failed asynchronous ++ * firmware requests, report that the fallback firmware was ++ * found. ++ */ ++ dev_info(dev->dev, "Using fallback firmware %s\n", ++ dev->devtype->firmware[dev->firmware]); ++ } ++ ++ /* allocate auxiliary per-device code buffer for the BIT processor */ ++ ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf", ++ dev->debugfs_root); ++ if (ret < 0) ++ goto put_pm; ++ ++ coda_copy_firmware(dev, fw->data, fw->size); ++ release_firmware(fw); ++ ++ ret = coda_hw_init(dev); ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, "HW initialization failed\n"); ++ goto put_pm; ++ } ++ ++ ret = coda_check_firmware(dev); ++ if (ret < 0) ++ goto put_pm; ++ ++ dev->m2m_dev = v4l2_m2m_init(&coda_m2m_ops); ++ if (IS_ERR(dev->m2m_dev)) { ++ v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); ++ goto put_pm; ++ } ++ ++ for (i = 0; i < dev->devtype->num_vdevs; i++) { ++ ret = coda_register_device(dev, i); ++ if (ret) { ++ v4l2_err(&dev->v4l2_dev, ++ "Failed to register %s video device: %d\n", ++ dev->devtype->vdevs[i]->name, ret); ++ goto rel_vfd; ++ } ++ } ++ ++ pm_runtime_put_sync(dev->dev); ++ return; ++ ++rel_vfd: ++ while (--i >= 0) ++ video_unregister_device(&dev->vfd[i]); ++ v4l2_m2m_release(dev->m2m_dev); ++put_pm: ++ pm_runtime_put_sync(dev->dev); ++} ++ ++enum coda_platform { ++ CODA_IMX27, ++ CODA_IMX51, ++ CODA_IMX53, ++ CODA_IMX6Q, ++ CODA_IMX6DL, ++}; ++ ++static const struct coda_devtype coda_devdata[] = { ++ [CODA_IMX27] = { ++ .firmware = { ++ "vpu_fw_imx27_TO2.bin", ++ "vpu/vpu_fw_imx27_TO2.bin", ++ "v4l-codadx6-imx27.bin" ++ }, ++ .product = CODA_DX6, ++ .codecs = codadx6_codecs, ++ .num_codecs = ARRAY_SIZE(codadx6_codecs), ++ .vdevs = codadx6_video_devices, ++ .num_vdevs = ARRAY_SIZE(codadx6_video_devices), ++ .workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024, ++ .iram_size = 0xb000, ++ }, ++ [CODA_IMX51] = { ++ .firmware = { ++ "vpu_fw_imx51.bin", ++ "vpu/vpu_fw_imx51.bin", ++ "v4l-codahx4-imx51.bin" ++ }, ++ .product = CODA_HX4, ++ .codecs = codahx4_codecs, ++ .num_codecs = ARRAY_SIZE(codahx4_codecs), ++ .vdevs = codahx4_video_devices, ++ .num_vdevs = ARRAY_SIZE(codahx4_video_devices), ++ .workbuf_size = 128 * 1024, ++ .tempbuf_size = 304 * 1024, ++ .iram_size = 0x14000, ++ }, ++ [CODA_IMX53] = { ++ .firmware = { ++ "vpu_fw_imx53.bin", ++ "vpu/vpu_fw_imx53.bin", ++ "v4l-coda7541-imx53.bin" ++ }, ++ .product = CODA_7541, ++ .codecs = coda7_codecs, ++ .num_codecs = ARRAY_SIZE(coda7_codecs), ++ .vdevs = coda7_video_devices, ++ .num_vdevs = ARRAY_SIZE(coda7_video_devices), ++ .workbuf_size = 128 * 1024, ++ .tempbuf_size = 304 * 1024, ++ .iram_size = 0x14000, ++ }, ++ [CODA_IMX6Q] = { ++ .firmware = { ++ "vpu_fw_imx6q.bin", ++ "vpu/vpu_fw_imx6q.bin", ++ "v4l-coda960-imx6q.bin" ++ }, ++ .product = CODA_960, ++ .codecs = coda9_codecs, ++ .num_codecs = ARRAY_SIZE(coda9_codecs), ++ .vdevs = coda9_video_devices, ++ .num_vdevs = ARRAY_SIZE(coda9_video_devices), ++ .workbuf_size = 80 * 1024, ++ .tempbuf_size = 204 * 1024, ++ .iram_size = 0x21000, ++ }, ++ [CODA_IMX6DL] = { ++ .firmware = { ++ "vpu_fw_imx6d.bin", ++ "vpu/vpu_fw_imx6d.bin", ++ "v4l-coda960-imx6dl.bin" ++ }, ++ .product = CODA_960, ++ .codecs = coda9_codecs, ++ .num_codecs = ARRAY_SIZE(coda9_codecs), ++ .vdevs = coda9_video_devices, ++ .num_vdevs = ARRAY_SIZE(coda9_video_devices), ++ .workbuf_size = 80 * 1024, ++ .tempbuf_size = 204 * 1024, ++ .iram_size = 0x1f000, /* leave 4k for suspend code */ ++ }, ++}; ++ ++static const struct of_device_id coda_dt_ids[] = { ++ { .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] }, ++ { .compatible = "fsl,imx51-vpu", .data = &coda_devdata[CODA_IMX51] }, ++ { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] }, ++ { .compatible = "fsl,imx6q-vpu", .data = &coda_devdata[CODA_IMX6Q] }, ++ { .compatible = "fsl,imx6dl-vpu", .data = &coda_devdata[CODA_IMX6DL] }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, coda_dt_ids); ++ ++static int coda_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct gen_pool *pool; ++ struct coda_dev *dev; ++ int ret, irq; ++ ++ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ ++ dev->devtype = of_device_get_match_data(&pdev->dev); ++ ++ dev->dev = &pdev->dev; ++ dev->clk_per = devm_clk_get(&pdev->dev, "per"); ++ if (IS_ERR(dev->clk_per)) { ++ dev_err(&pdev->dev, "Could not get per clock\n"); ++ return PTR_ERR(dev->clk_per); ++ } ++ ++ dev->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); ++ if (IS_ERR(dev->clk_ahb)) { ++ dev_err(&pdev->dev, "Could not get ahb clock\n"); ++ return PTR_ERR(dev->clk_ahb); ++ } ++ ++ /* Get memory for physical registers */ ++ dev->regs_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(dev->regs_base)) ++ return PTR_ERR(dev->regs_base); ++ ++ /* IRQ */ ++ irq = platform_get_irq_byname(pdev, "bit"); ++ if (irq < 0) ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ ret = devm_request_irq(&pdev->dev, irq, coda_irq_handler, 0, ++ CODA_NAME "-video", dev); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request irq: %d\n", ret); ++ return ret; ++ } ++ ++ /* JPEG IRQ */ ++ if (dev->devtype->product == CODA_960) { ++ irq = platform_get_irq_byname(pdev, "jpeg"); ++ if (irq < 0) ++ return irq; ++ ++ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, ++ coda9_jpeg_irq_handler, ++ IRQF_ONESHOT, CODA_NAME "-jpeg", ++ dev); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request jpeg irq\n"); ++ return ret; ++ } ++ } ++ ++ dev->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, ++ NULL); ++ if (IS_ERR(dev->rstc)) { ++ ret = PTR_ERR(dev->rstc); ++ dev_err(&pdev->dev, "failed get reset control: %d\n", ret); ++ return ret; ++ } ++ ++ /* Get IRAM pool from device tree */ ++ pool = of_gen_pool_get(np, "iram", 0); ++ if (!pool) { ++ dev_err(&pdev->dev, "iram pool not available\n"); ++ return -ENOMEM; ++ } ++ dev->iram_pool = pool; ++ ++ /* Get vdoa_data if supported by the platform */ ++ dev->vdoa = coda_get_vdoa_data(); ++ if (PTR_ERR(dev->vdoa) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ ++ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); ++ if (ret) ++ return ret; ++ ++ ratelimit_default_init(&dev->mb_err_rs); ++ mutex_init(&dev->dev_mutex); ++ mutex_init(&dev->coda_mutex); ++ ida_init(&dev->ida); ++ ++ dev->debugfs_root = debugfs_create_dir("coda", NULL); ++ ++ /* allocate auxiliary per-device buffers for the BIT processor */ ++ if (dev->devtype->product == CODA_DX6) { ++ ret = coda_alloc_aux_buf(dev, &dev->workbuf, ++ dev->devtype->workbuf_size, "workbuf", ++ dev->debugfs_root); ++ if (ret < 0) ++ goto err_v4l2_register; ++ } ++ ++ if (dev->devtype->tempbuf_size) { ++ ret = coda_alloc_aux_buf(dev, &dev->tempbuf, ++ dev->devtype->tempbuf_size, "tempbuf", ++ dev->debugfs_root); ++ if (ret < 0) ++ goto err_v4l2_register; ++ } ++ ++ dev->iram.size = dev->devtype->iram_size; ++ dev->iram.vaddr = gen_pool_dma_alloc(dev->iram_pool, dev->iram.size, ++ &dev->iram.paddr); ++ if (!dev->iram.vaddr) { ++ dev_warn(&pdev->dev, "unable to alloc iram\n"); ++ } else { ++ memset(dev->iram.vaddr, 0, dev->iram.size); ++ dev->iram.blob.data = dev->iram.vaddr; ++ dev->iram.blob.size = dev->iram.size; ++ dev->iram.dentry = debugfs_create_blob("iram", 0444, ++ dev->debugfs_root, ++ &dev->iram.blob); ++ } ++ ++ dev->workqueue = alloc_ordered_workqueue("coda", WQ_MEM_RECLAIM); ++ if (!dev->workqueue) { ++ dev_err(&pdev->dev, "unable to alloc workqueue\n"); ++ ret = -ENOMEM; ++ goto err_v4l2_register; ++ } ++ ++ platform_set_drvdata(pdev, dev); ++ ++ /* ++ * Start activated so we can directly call coda_hw_init in ++ * coda_fw_callback regardless of whether CONFIG_PM is ++ * enabled or whether the device is associated with a PM domain. ++ */ ++ pm_runtime_get_noresume(&pdev->dev); ++ pm_runtime_set_active(&pdev->dev); ++ pm_runtime_enable(&pdev->dev); ++ ++ ret = coda_firmware_request(dev); ++ if (ret) ++ goto err_alloc_workqueue; ++ return 0; ++ ++err_alloc_workqueue: ++ pm_runtime_disable(&pdev->dev); ++ pm_runtime_put_noidle(&pdev->dev); ++ destroy_workqueue(dev->workqueue); ++err_v4l2_register: ++ v4l2_device_unregister(&dev->v4l2_dev); ++ return ret; ++} ++ ++static void coda_remove(struct platform_device *pdev) ++{ ++ struct coda_dev *dev = platform_get_drvdata(pdev); ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dev->vfd); i++) { ++ if (video_get_drvdata(&dev->vfd[i])) ++ video_unregister_device(&dev->vfd[i]); ++ } ++ if (dev->m2m_dev) ++ v4l2_m2m_release(dev->m2m_dev); ++ pm_runtime_disable(&pdev->dev); ++ v4l2_device_unregister(&dev->v4l2_dev); ++ destroy_workqueue(dev->workqueue); ++ if (dev->iram.vaddr) ++ gen_pool_free(dev->iram_pool, (unsigned long)dev->iram.vaddr, ++ dev->iram.size); ++ coda_free_aux_buf(dev, &dev->codebuf); ++ coda_free_aux_buf(dev, &dev->tempbuf); ++ coda_free_aux_buf(dev, &dev->workbuf); ++ debugfs_remove_recursive(dev->debugfs_root); ++ ida_destroy(&dev->ida); ++} ++ ++#ifdef CONFIG_PM ++static int coda_runtime_resume(struct device *dev) ++{ ++ struct coda_dev *cdev = dev_get_drvdata(dev); ++ int ret = 0; ++ ++ if (dev->pm_domain && cdev->codebuf.vaddr) { ++ ret = coda_hw_init(cdev); ++ if (ret) ++ v4l2_err(&cdev->v4l2_dev, "HW initialization failed\n"); ++ } ++ ++ return ret; ++} ++#endif ++ ++static const struct dev_pm_ops coda_pm_ops = { ++ SET_RUNTIME_PM_OPS(NULL, coda_runtime_resume, NULL) ++}; ++ ++static struct platform_driver coda_driver = { ++ .probe = coda_probe, ++ .remove_new = coda_remove, ++ .driver = { ++ .name = CODA_NAME, ++ .of_match_table = coda_dt_ids, ++ .pm = &coda_pm_ops, ++ }, ++}; ++ ++module_platform_driver(coda_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Javier Martin "); ++MODULE_DESCRIPTION("Coda multi-standard codec V4L2 driver"); +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-gdi.c b/drivers/media/platform/chips-media/coda/coda-gdi.c +--- a/drivers/media/platform/chips-media/coda/coda-gdi.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda-gdi.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,146 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Coda multi-standard codec IP ++ * ++ * Copyright (C) 2014 Philipp Zabel, Pengutronix ++ */ ++ ++#include ++#include "coda.h" ++ ++#define XY2_INVERT BIT(7) ++#define XY2_ZERO BIT(6) ++#define XY2_TB_XOR BIT(5) ++#define XY2_XYSEL BIT(4) ++#define XY2_Y (1 << 4) ++#define XY2_X (0 << 4) ++ ++#define XY2(luma_sel, luma_bit, chroma_sel, chroma_bit) \ ++ (((XY2_##luma_sel) | (luma_bit)) << 8 | \ ++ (XY2_##chroma_sel) | (chroma_bit)) ++ ++static const u16 xy2ca_zero_map[16] = { ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++}; ++ ++static const u16 xy2ca_tiled_map[16] = { ++ XY2(Y, 0, Y, 0), ++ XY2(Y, 1, Y, 1), ++ XY2(Y, 2, Y, 2), ++ XY2(Y, 3, X, 3), ++ XY2(X, 3, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++ XY2(ZERO, 0, ZERO, 0), ++}; ++ ++/* ++ * RA[15:0], CA[15:8] are hardwired to contain the 24-bit macroblock ++ * start offset (macroblock size is 16x16 for luma, 16x8 for chroma). ++ * Bits CA[4:0] are set using XY2CA above. BA[3:0] seems to be unused. ++ */ ++ ++#define RBC_CA (0 << 4) ++#define RBC_BA (1 << 4) ++#define RBC_RA (2 << 4) ++#define RBC_ZERO (3 << 4) ++ ++#define RBC(luma_sel, luma_bit, chroma_sel, chroma_bit) \ ++ (((RBC_##luma_sel) | (luma_bit)) << 6 | \ ++ (RBC_##chroma_sel) | (chroma_bit)) ++ ++static const u16 rbc2axi_tiled_map[32] = { ++ RBC(ZERO, 0, ZERO, 0), ++ RBC(ZERO, 0, ZERO, 0), ++ RBC(ZERO, 0, ZERO, 0), ++ RBC(CA, 0, CA, 0), ++ RBC(CA, 1, CA, 1), ++ RBC(CA, 2, CA, 2), ++ RBC(CA, 3, CA, 3), ++ RBC(CA, 4, CA, 8), ++ RBC(CA, 8, CA, 9), ++ RBC(CA, 9, CA, 10), ++ RBC(CA, 10, CA, 11), ++ RBC(CA, 11, CA, 12), ++ RBC(CA, 12, CA, 13), ++ RBC(CA, 13, CA, 14), ++ RBC(CA, 14, CA, 15), ++ RBC(CA, 15, RA, 0), ++ RBC(RA, 0, RA, 1), ++ RBC(RA, 1, RA, 2), ++ RBC(RA, 2, RA, 3), ++ RBC(RA, 3, RA, 4), ++ RBC(RA, 4, RA, 5), ++ RBC(RA, 5, RA, 6), ++ RBC(RA, 6, RA, 7), ++ RBC(RA, 7, RA, 8), ++ RBC(RA, 8, RA, 9), ++ RBC(RA, 9, RA, 10), ++ RBC(RA, 10, RA, 11), ++ RBC(RA, 11, RA, 12), ++ RBC(RA, 12, RA, 13), ++ RBC(RA, 13, RA, 14), ++ RBC(RA, 14, RA, 15), ++ RBC(RA, 15, ZERO, 0), ++}; ++ ++void coda_set_gdi_regs(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ const u16 *xy2ca_map; ++ u32 xy2rbc_config; ++ int i; ++ ++ switch (ctx->tiled_map_type) { ++ case GDI_LINEAR_FRAME_MAP: ++ default: ++ xy2ca_map = xy2ca_zero_map; ++ xy2rbc_config = 0; ++ break; ++ case GDI_TILED_FRAME_MB_RASTER_MAP: ++ xy2ca_map = xy2ca_tiled_map; ++ xy2rbc_config = CODA9_XY2RBC_TILED_MAP | ++ CODA9_XY2RBC_CA_INC_HOR | ++ (16 - 1) << 12 | (8 - 1) << 4; ++ break; ++ } ++ ++ for (i = 0; i < 16; i++) ++ coda_write(dev, xy2ca_map[i], ++ CODA9_GDI_XY2_CAS_0 + 4 * i); ++ for (i = 0; i < 4; i++) ++ coda_write(dev, XY2(ZERO, 0, ZERO, 0), ++ CODA9_GDI_XY2_BA_0 + 4 * i); ++ for (i = 0; i < 16; i++) ++ coda_write(dev, XY2(ZERO, 0, ZERO, 0), ++ CODA9_GDI_XY2_RAS_0 + 4 * i); ++ coda_write(dev, xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG); ++ if (xy2rbc_config) { ++ for (i = 0; i < 32; i++) ++ coda_write(dev, rbc2axi_tiled_map[i], ++ CODA9_GDI_RBC2_AXI_0 + 4 * i); ++ } ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda.h b/drivers/media/platform/chips-media/coda/coda.h +--- a/drivers/media/platform/chips-media/coda/coda.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,403 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Coda multi-standard codec IP ++ * ++ * Copyright (C) 2012 Vista Silicon S.L. ++ * Javier Martin, ++ * Xavier Duret ++ * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix ++ */ ++ ++#ifndef __CODA_H__ ++#define __CODA_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "coda_regs.h" ++ ++#define CODA_MAX_FRAMEBUFFERS 19 ++#define FMO_SLICE_SAVE_BUF_SIZE (32) ++ ++/* ++ * This control allows applications to read the per-stream ++ * (i.e. per-context) Macroblocks Error Count. This value ++ * is CODA specific. ++ */ ++#define V4L2_CID_CODA_MB_ERR_CNT (V4L2_CID_USER_CODA_BASE + 0) ++ ++enum { ++ V4L2_M2M_SRC = 0, ++ V4L2_M2M_DST = 1, ++}; ++ ++enum coda_inst_type { ++ CODA_INST_ENCODER, ++ CODA_INST_DECODER, ++}; ++ ++enum coda_product { ++ CODA_DX6 = 0xf001, ++ CODA_HX4 = 0xf00a, ++ CODA_7541 = 0xf012, ++ CODA_960 = 0xf020, ++}; ++ ++struct coda_video_device; ++ ++struct coda_devtype { ++ char *firmware[3]; ++ enum coda_product product; ++ const struct coda_codec *codecs; ++ unsigned int num_codecs; ++ const struct coda_video_device **vdevs; ++ unsigned int num_vdevs; ++ size_t workbuf_size; ++ size_t tempbuf_size; ++ size_t iram_size; ++}; ++ ++struct coda_aux_buf { ++ void *vaddr; ++ dma_addr_t paddr; ++ u32 size; ++ struct debugfs_blob_wrapper blob; ++ struct dentry *dentry; ++}; ++ ++struct coda_dev { ++ struct v4l2_device v4l2_dev; ++ struct video_device vfd[6]; ++ struct device *dev; ++ const struct coda_devtype *devtype; ++ int firmware; ++ struct vdoa_data *vdoa; ++ ++ void __iomem *regs_base; ++ struct clk *clk_per; ++ struct clk *clk_ahb; ++ struct reset_control *rstc; ++ ++ struct coda_aux_buf codebuf; ++ struct coda_aux_buf tempbuf; ++ struct coda_aux_buf workbuf; ++ struct gen_pool *iram_pool; ++ struct coda_aux_buf iram; ++ ++ struct mutex dev_mutex; ++ struct mutex coda_mutex; ++ struct workqueue_struct *workqueue; ++ struct v4l2_m2m_dev *m2m_dev; ++ struct ida ida; ++ struct dentry *debugfs_root; ++ struct ratelimit_state mb_err_rs; ++}; ++ ++struct coda_codec { ++ u32 mode; ++ u32 src_fourcc; ++ u32 dst_fourcc; ++ u32 max_w; ++ u32 max_h; ++}; ++ ++struct coda_huff_tab; ++ ++struct coda_params { ++ u8 rot_mode; ++ u8 h264_intra_qp; ++ u8 h264_inter_qp; ++ u8 h264_min_qp; ++ u8 h264_max_qp; ++ u8 h264_disable_deblocking_filter_idc; ++ s8 h264_slice_alpha_c0_offset_div2; ++ s8 h264_slice_beta_offset_div2; ++ bool h264_constrained_intra_pred_flag; ++ s8 h264_chroma_qp_index_offset; ++ u8 h264_profile_idc; ++ u8 h264_level_idc; ++ u8 mpeg2_profile_idc; ++ u8 mpeg2_level_idc; ++ u8 mpeg4_intra_qp; ++ u8 mpeg4_inter_qp; ++ u8 gop_size; ++ int intra_refresh; ++ enum v4l2_jpeg_chroma_subsampling jpeg_chroma_subsampling; ++ u8 jpeg_quality; ++ u8 jpeg_restart_interval; ++ u8 *jpeg_qmat_tab[3]; ++ int jpeg_qmat_index[3]; ++ int jpeg_huff_dc_index[3]; ++ int jpeg_huff_ac_index[3]; ++ u32 *jpeg_huff_data; ++ struct coda_huff_tab *jpeg_huff_tab; ++ int codec_mode; ++ int codec_mode_aux; ++ enum v4l2_mpeg_video_multi_slice_mode slice_mode; ++ u32 framerate; ++ u16 bitrate; ++ u16 vbv_delay; ++ u32 vbv_size; ++ u32 slice_max_bits; ++ u32 slice_max_mb; ++ bool force_ipicture; ++ bool gop_size_changed; ++ bool bitrate_changed; ++ bool framerate_changed; ++ bool h264_intra_qp_changed; ++ bool intra_refresh_changed; ++ bool slice_mode_changed; ++ bool frame_rc_enable; ++ bool mb_rc_enable; ++}; ++ ++struct coda_buffer_meta { ++ struct list_head list; ++ u32 sequence; ++ struct v4l2_timecode timecode; ++ u64 timestamp; ++ unsigned int start; ++ unsigned int end; ++ bool last; ++}; ++ ++/* Per-queue, driver-specific private data */ ++struct coda_q_data { ++ unsigned int width; ++ unsigned int height; ++ unsigned int bytesperline; ++ unsigned int sizeimage; ++ unsigned int fourcc; ++ struct v4l2_rect rect; ++}; ++ ++struct coda_iram_info { ++ u32 axi_sram_use; ++ phys_addr_t buf_bit_use; ++ phys_addr_t buf_ip_ac_dc_use; ++ phys_addr_t buf_dbk_y_use; ++ phys_addr_t buf_dbk_c_use; ++ phys_addr_t buf_ovl_use; ++ phys_addr_t buf_btp_use; ++ phys_addr_t search_ram_paddr; ++ int search_ram_size; ++ int remaining; ++ phys_addr_t next_paddr; ++}; ++ ++#define GDI_LINEAR_FRAME_MAP 0 ++#define GDI_TILED_FRAME_MB_RASTER_MAP 1 ++ ++struct coda_ctx; ++ ++struct coda_context_ops { ++ int (*queue_init)(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq); ++ int (*reqbufs)(struct coda_ctx *ctx, struct v4l2_requestbuffers *rb); ++ int (*start_streaming)(struct coda_ctx *ctx); ++ int (*prepare_run)(struct coda_ctx *ctx); ++ void (*finish_run)(struct coda_ctx *ctx); ++ void (*run_timeout)(struct coda_ctx *ctx); ++ void (*seq_init_work)(struct work_struct *work); ++ void (*seq_end_work)(struct work_struct *work); ++ void (*release)(struct coda_ctx *ctx); ++}; ++ ++struct coda_internal_frame { ++ struct coda_aux_buf buf; ++ struct coda_buffer_meta meta; ++ u32 type; ++ u32 error; ++}; ++ ++struct coda_ctx { ++ struct coda_dev *dev; ++ struct mutex buffer_mutex; ++ struct work_struct pic_run_work; ++ struct work_struct seq_init_work; ++ struct work_struct seq_end_work; ++ struct completion completion; ++ const struct coda_video_device *cvd; ++ const struct coda_context_ops *ops; ++ int aborting; ++ int initialized; ++ int streamon_out; ++ int streamon_cap; ++ u32 qsequence; ++ u32 osequence; ++ u32 sequence_offset; ++ struct coda_q_data q_data[2]; ++ enum coda_inst_type inst_type; ++ const struct coda_codec *codec; ++ enum v4l2_colorspace colorspace; ++ enum v4l2_xfer_func xfer_func; ++ enum v4l2_ycbcr_encoding ycbcr_enc; ++ enum v4l2_quantization quantization; ++ struct coda_params params; ++ struct v4l2_ctrl_handler ctrls; ++ struct v4l2_ctrl *h264_profile_ctrl; ++ struct v4l2_ctrl *h264_level_ctrl; ++ struct v4l2_ctrl *mpeg2_profile_ctrl; ++ struct v4l2_ctrl *mpeg2_level_ctrl; ++ struct v4l2_ctrl *mpeg4_profile_ctrl; ++ struct v4l2_ctrl *mpeg4_level_ctrl; ++ struct v4l2_ctrl *mb_err_cnt_ctrl; ++ struct v4l2_fh fh; ++ int gopcounter; ++ int runcounter; ++ int jpeg_ecs_offset; ++ char vpu_header[3][64]; ++ int vpu_header_size[3]; ++ struct kfifo bitstream_fifo; ++ struct mutex bitstream_mutex; ++ struct coda_aux_buf bitstream; ++ bool hold; ++ struct coda_aux_buf parabuf; ++ struct coda_aux_buf psbuf; ++ struct coda_aux_buf slicebuf; ++ struct coda_internal_frame internal_frames[CODA_MAX_FRAMEBUFFERS]; ++ struct list_head buffer_meta_list; ++ spinlock_t buffer_meta_lock; ++ int num_metas; ++ unsigned int first_frame_sequence; ++ struct coda_aux_buf workbuf; ++ int num_internal_frames; ++ int idx; ++ int reg_idx; ++ struct coda_iram_info iram_info; ++ int tiled_map_type; ++ u32 bit_stream_param; ++ u32 frm_dis_flg; ++ u32 frame_mem_ctrl; ++ u32 para_change; ++ int display_idx; ++ struct dentry *debugfs_entry; ++ bool use_bit; ++ bool use_vdoa; ++ struct vdoa_ctx *vdoa; ++ /* ++ * wakeup mutex used to serialize encoder stop command and finish_run, ++ * ensures that finish_run always either flags the last returned buffer ++ * or wakes up the capture queue to signal EOS afterwards. ++ */ ++ struct mutex wakeup_mutex; ++}; ++ ++extern int coda_debug; ++ ++#define coda_dbg(level, ctx, fmt, arg...) \ ++ do { \ ++ if (coda_debug >= (level)) \ ++ v4l2_dbg((level), coda_debug, &(ctx)->dev->v4l2_dev, \ ++ "%u: " fmt, (ctx)->idx, ##arg); \ ++ } while (0) ++ ++void coda_write(struct coda_dev *dev, u32 data, u32 reg); ++unsigned int coda_read(struct coda_dev *dev, u32 reg); ++void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data, ++ struct vb2_v4l2_buffer *buf, unsigned int reg_y); ++ ++int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf, ++ size_t size, const char *name, struct dentry *parent); ++void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf); ++ ++int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq); ++int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, ++ struct vb2_queue *dst_vq); ++ ++int coda_hw_reset(struct coda_ctx *ctx); ++ ++void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list); ++ ++void coda_set_gdi_regs(struct coda_ctx *ctx); ++ ++static inline struct coda_q_data *get_q_data(struct coda_ctx *ctx, ++ enum v4l2_buf_type type) ++{ ++ switch (type) { ++ case V4L2_BUF_TYPE_VIDEO_OUTPUT: ++ return &(ctx->q_data[V4L2_M2M_SRC]); ++ case V4L2_BUF_TYPE_VIDEO_CAPTURE: ++ return &(ctx->q_data[V4L2_M2M_DST]); ++ default: ++ return NULL; ++ } ++} ++ ++const char *coda_product_name(int product); ++ ++int coda_check_firmware(struct coda_dev *dev); ++ ++static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx) ++{ ++ return kfifo_len(&ctx->bitstream_fifo); ++} ++ ++/* ++ * The bitstream prefetcher needs to read at least 2 256 byte periods past ++ * the desired bitstream position for all data to reach the decoder. ++ */ ++static inline bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, ++ unsigned int pos) ++{ ++ return (int)(ctx->bitstream_fifo.kfifo.in - ALIGN(pos, 256)) > 512; ++} ++ ++bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos); ++int coda_bitstream_flush(struct coda_ctx *ctx); ++ ++void coda_bit_stream_end_flag(struct coda_ctx *ctx); ++ ++void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, ++ enum vb2_buffer_state state); ++ ++int coda_h264_filler_nal(int size, char *p); ++int coda_h264_padding(int size, char *p); ++int coda_h264_profile(int profile_idc); ++int coda_h264_level(int level_idc); ++int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb); ++int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf, ++ int *size, int max_size); ++ ++int coda_mpeg2_profile(int profile_idc); ++int coda_mpeg2_level(int level_idc); ++u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size); ++int coda_mpeg4_profile(int profile_idc); ++int coda_mpeg4_level(int level_idc); ++u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size); ++ ++void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc, ++ u8 level_idc); ++ ++static inline int coda_jpeg_scale(int src, int dst) ++{ ++ return (dst <= src / 8) ? 3 : ++ (dst <= src / 4) ? 2 : ++ (dst <= src / 2) ? 1 : 0; ++} ++ ++bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb); ++int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb); ++int coda_jpeg_write_tables(struct coda_ctx *ctx); ++void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality); ++ ++extern const struct coda_context_ops coda_bit_encode_ops; ++extern const struct coda_context_ops coda_bit_decode_ops; ++extern const struct coda_context_ops coda9_jpeg_encode_ops; ++extern const struct coda_context_ops coda9_jpeg_decode_ops; ++ ++irqreturn_t coda_irq_handler(int irq, void *data); ++irqreturn_t coda9_jpeg_irq_handler(int irq, void *data); ++ ++#endif /* __CODA_H__ */ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-h264.c b/drivers/media/platform/chips-media/coda/coda-h264.c +--- a/drivers/media/platform/chips-media/coda/coda-h264.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda-h264.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,429 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Coda multi-standard codec IP - H.264 helper functions ++ * ++ * Copyright (C) 2012 Vista Silicon S.L. ++ * Javier Martin, ++ * Xavier Duret ++ */ ++ ++#include ++#include ++#include ++ ++#include "coda.h" ++ ++static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 }; ++ ++static const u8 *coda_find_nal_header(const u8 *buf, const u8 *end) ++{ ++ u32 val = 0xffffffff; ++ ++ do { ++ val = val << 8 | *buf++; ++ if (buf >= end) ++ return NULL; ++ } while (val != 0x00000001); ++ ++ return buf; ++} ++ ++int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb) ++{ ++ const u8 *buf = vb2_plane_vaddr(vb, 0); ++ const u8 *end = buf + vb2_get_plane_payload(vb, 0); ++ ++ /* Find SPS header */ ++ do { ++ buf = coda_find_nal_header(buf, end); ++ if (!buf) ++ return -EINVAL; ++ } while ((*buf++ & 0x1f) != 0x7); ++ ++ ctx->params.h264_profile_idc = buf[0]; ++ ctx->params.h264_level_idc = buf[2]; ++ ++ return 0; ++} ++ ++int coda_h264_filler_nal(int size, char *p) ++{ ++ if (size < 6) ++ return -EINVAL; ++ ++ p[0] = 0x00; ++ p[1] = 0x00; ++ p[2] = 0x00; ++ p[3] = 0x01; ++ p[4] = 0x0c; ++ memset(p + 5, 0xff, size - 6); ++ /* Add rbsp stop bit and trailing at the end */ ++ p[size - 1] = 0x80; ++ ++ return 0; ++} ++ ++int coda_h264_padding(int size, char *p) ++{ ++ int nal_size; ++ int diff; ++ ++ diff = size - (size & ~0x7); ++ if (diff == 0) ++ return 0; ++ ++ nal_size = coda_filler_size[diff]; ++ coda_h264_filler_nal(nal_size, p); ++ ++ return nal_size; ++} ++ ++int coda_h264_profile(int profile_idc) ++{ ++ switch (profile_idc) { ++ case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; ++ case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN; ++ case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED; ++ case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; ++ default: return -EINVAL; ++ } ++} ++ ++int coda_h264_level(int level_idc) ++{ ++ switch (level_idc) { ++ case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0; ++ case 9: return V4L2_MPEG_VIDEO_H264_LEVEL_1B; ++ case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1; ++ case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2; ++ case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3; ++ case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0; ++ case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1; ++ case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2; ++ case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0; ++ case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1; ++ case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2; ++ case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0; ++ case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1; ++ case 42: return V4L2_MPEG_VIDEO_H264_LEVEL_4_2; ++ case 50: return V4L2_MPEG_VIDEO_H264_LEVEL_5_0; ++ case 51: return V4L2_MPEG_VIDEO_H264_LEVEL_5_1; ++ default: return -EINVAL; ++ } ++} ++ ++struct rbsp { ++ char *buf; ++ int size; ++ int pos; ++}; ++ ++static inline int rbsp_read_bit(struct rbsp *rbsp) ++{ ++ int shift = 7 - (rbsp->pos % 8); ++ int ofs = rbsp->pos++ / 8; ++ ++ if (ofs >= rbsp->size) ++ return -EINVAL; ++ ++ return (rbsp->buf[ofs] >> shift) & 1; ++} ++ ++static inline int rbsp_write_bit(struct rbsp *rbsp, int bit) ++{ ++ int shift = 7 - (rbsp->pos % 8); ++ int ofs = rbsp->pos++ / 8; ++ ++ if (ofs >= rbsp->size) ++ return -EINVAL; ++ ++ rbsp->buf[ofs] &= ~(1 << shift); ++ rbsp->buf[ofs] |= bit << shift; ++ ++ return 0; ++} ++ ++static inline int rbsp_read_bits(struct rbsp *rbsp, int num, int *val) ++{ ++ int i, ret; ++ int tmp = 0; ++ ++ if (num > 32) ++ return -EINVAL; ++ ++ for (i = 0; i < num; i++) { ++ ret = rbsp_read_bit(rbsp); ++ if (ret < 0) ++ return ret; ++ tmp |= ret << (num - i - 1); ++ } ++ ++ if (val) ++ *val = tmp; ++ ++ return 0; ++} ++ ++static int rbsp_write_bits(struct rbsp *rbsp, int num, int value) ++{ ++ int ret; ++ ++ while (num--) { ++ ret = rbsp_write_bit(rbsp, (value >> num) & 1); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rbsp_read_uev(struct rbsp *rbsp, unsigned int *val) ++{ ++ int leading_zero_bits = 0; ++ unsigned int tmp = 0; ++ int ret; ++ ++ while ((ret = rbsp_read_bit(rbsp)) == 0) ++ leading_zero_bits++; ++ if (ret < 0) ++ return ret; ++ ++ if (leading_zero_bits > 0) { ++ ret = rbsp_read_bits(rbsp, leading_zero_bits, &tmp); ++ if (ret) ++ return ret; ++ } ++ ++ if (val) ++ *val = (1 << leading_zero_bits) - 1 + tmp; ++ ++ return 0; ++} ++ ++static int rbsp_write_uev(struct rbsp *rbsp, unsigned int value) ++{ ++ int i; ++ int ret; ++ int tmp = value + 1; ++ int leading_zero_bits = fls(tmp) - 1; ++ ++ for (i = 0; i < leading_zero_bits; i++) { ++ ret = rbsp_write_bit(rbsp, 0); ++ if (ret) ++ return ret; ++ } ++ ++ return rbsp_write_bits(rbsp, leading_zero_bits + 1, tmp); ++} ++ ++static int rbsp_read_sev(struct rbsp *rbsp, int *val) ++{ ++ unsigned int tmp; ++ int ret; ++ ++ ret = rbsp_read_uev(rbsp, &tmp); ++ if (ret) ++ return ret; ++ ++ if (val) { ++ if (tmp & 1) ++ *val = (tmp + 1) / 2; ++ else ++ *val = -(tmp / 2); ++ } ++ ++ return 0; ++} ++ ++/** ++ * coda_h264_sps_fixup - fixes frame cropping values in h.264 SPS ++ * @ctx: encoder context ++ * @width: visible width ++ * @height: visible height ++ * @buf: buffer containing h.264 SPS RBSP, starting with NAL header ++ * @size: modified RBSP size return value ++ * @max_size: available size in buf ++ * ++ * Rewrites the frame cropping values in an h.264 SPS RBSP correctly for the ++ * given visible width and height. ++ */ ++int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf, ++ int *size, int max_size) ++{ ++ int profile_idc; ++ unsigned int pic_order_cnt_type; ++ int pic_width_in_mbs_minus1, pic_height_in_map_units_minus1; ++ int frame_mbs_only_flag, frame_cropping_flag; ++ int vui_parameters_present_flag; ++ unsigned int crop_right, crop_bottom; ++ struct rbsp sps; ++ int pos; ++ int ret; ++ ++ if (*size < 8 || *size >= max_size) ++ return -EINVAL; ++ ++ sps.buf = buf + 5; /* Skip NAL header */ ++ sps.size = *size - 5; ++ ++ profile_idc = sps.buf[0]; ++ /* Skip constraint_set[0-5]_flag, reserved_zero_2bits */ ++ /* Skip level_idc */ ++ sps.pos = 24; ++ ++ /* seq_parameter_set_id */ ++ ret = rbsp_read_uev(&sps, NULL); ++ if (ret) ++ return ret; ++ ++ if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || ++ profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || ++ profile_idc == 86 || profile_idc == 118 || profile_idc == 128 || ++ profile_idc == 138 || profile_idc == 139 || profile_idc == 134 || ++ profile_idc == 135) { ++ dev_err(ctx->fh.vdev->dev_parent, ++ "%s: Handling profile_idc %d not implemented\n", ++ __func__, profile_idc); ++ return -EINVAL; ++ } ++ ++ /* log2_max_frame_num_minus4 */ ++ ret = rbsp_read_uev(&sps, NULL); ++ if (ret) ++ return ret; ++ ++ ret = rbsp_read_uev(&sps, &pic_order_cnt_type); ++ if (ret) ++ return ret; ++ ++ if (pic_order_cnt_type == 0) { ++ /* log2_max_pic_order_cnt_lsb_minus4 */ ++ ret = rbsp_read_uev(&sps, NULL); ++ if (ret) ++ return ret; ++ } else if (pic_order_cnt_type == 1) { ++ unsigned int i, num_ref_frames_in_pic_order_cnt_cycle; ++ ++ /* delta_pic_order_always_zero_flag */ ++ ret = rbsp_read_bit(&sps); ++ if (ret < 0) ++ return ret; ++ /* offset_for_non_ref_pic */ ++ ret = rbsp_read_sev(&sps, NULL); ++ if (ret) ++ return ret; ++ /* offset_for_top_to_bottom_field */ ++ ret = rbsp_read_sev(&sps, NULL); ++ if (ret) ++ return ret; ++ ++ ret = rbsp_read_uev(&sps, ++ &num_ref_frames_in_pic_order_cnt_cycle); ++ if (ret) ++ return ret; ++ for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) { ++ /* offset_for_ref_frame */ ++ ret = rbsp_read_sev(&sps, NULL); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ /* max_num_ref_frames */ ++ ret = rbsp_read_uev(&sps, NULL); ++ if (ret) ++ return ret; ++ ++ /* gaps_in_frame_num_value_allowed_flag */ ++ ret = rbsp_read_bit(&sps); ++ if (ret < 0) ++ return ret; ++ ret = rbsp_read_uev(&sps, &pic_width_in_mbs_minus1); ++ if (ret) ++ return ret; ++ ret = rbsp_read_uev(&sps, &pic_height_in_map_units_minus1); ++ if (ret) ++ return ret; ++ frame_mbs_only_flag = ret = rbsp_read_bit(&sps); ++ if (ret < 0) ++ return ret; ++ if (!frame_mbs_only_flag) { ++ /* mb_adaptive_frame_field_flag */ ++ ret = rbsp_read_bit(&sps); ++ if (ret < 0) ++ return ret; ++ } ++ /* direct_8x8_inference_flag */ ++ ret = rbsp_read_bit(&sps); ++ if (ret < 0) ++ return ret; ++ ++ /* Mark position of the frame cropping flag */ ++ pos = sps.pos; ++ frame_cropping_flag = ret = rbsp_read_bit(&sps); ++ if (ret < 0) ++ return ret; ++ if (frame_cropping_flag) { ++ unsigned int crop_left, crop_top; ++ ++ ret = rbsp_read_uev(&sps, &crop_left); ++ if (ret) ++ return ret; ++ ret = rbsp_read_uev(&sps, &crop_right); ++ if (ret) ++ return ret; ++ ret = rbsp_read_uev(&sps, &crop_top); ++ if (ret) ++ return ret; ++ ret = rbsp_read_uev(&sps, &crop_bottom); ++ if (ret) ++ return ret; ++ } ++ vui_parameters_present_flag = ret = rbsp_read_bit(&sps); ++ if (ret < 0) ++ return ret; ++ if (vui_parameters_present_flag) { ++ dev_err(ctx->fh.vdev->dev_parent, ++ "%s: Handling vui_parameters not implemented\n", ++ __func__); ++ return -EINVAL; ++ } ++ ++ crop_right = round_up(width, 16) - width; ++ crop_bottom = round_up(height, 16) - height; ++ crop_right /= 2; ++ if (frame_mbs_only_flag) ++ crop_bottom /= 2; ++ else ++ crop_bottom /= 4; ++ ++ ++ sps.size = max_size - 5; ++ sps.pos = pos; ++ frame_cropping_flag = 1; ++ ret = rbsp_write_bit(&sps, frame_cropping_flag); ++ if (ret) ++ return ret; ++ ret = rbsp_write_uev(&sps, 0); /* crop_left */ ++ if (ret) ++ return ret; ++ ret = rbsp_write_uev(&sps, crop_right); ++ if (ret) ++ return ret; ++ ret = rbsp_write_uev(&sps, 0); /* crop_top */ ++ if (ret) ++ return ret; ++ ret = rbsp_write_uev(&sps, crop_bottom); ++ if (ret) ++ return ret; ++ ret = rbsp_write_bit(&sps, 0); /* vui_parameters_present_flag */ ++ if (ret) ++ return ret; ++ ret = rbsp_write_bit(&sps, 1); ++ if (ret) ++ return ret; ++ ++ *size = 5 + DIV_ROUND_UP(sps.pos, 8); ++ ++ return 0; ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-jpeg.c b/drivers/media/platform/chips-media/coda/coda-jpeg.c +--- a/drivers/media/platform/chips-media/coda/coda-jpeg.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda-jpeg.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,1547 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Coda multi-standard codec IP - JPEG support functions ++ * ++ * Copyright (C) 2014 Philipp Zabel, Pengutronix ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "coda.h" ++#include "trace.h" ++ ++#define SOI_MARKER 0xffd8 ++#define APP9_MARKER 0xffe9 ++#define DRI_MARKER 0xffdd ++#define DQT_MARKER 0xffdb ++#define DHT_MARKER 0xffc4 ++#define SOF_MARKER 0xffc0 ++#define SOS_MARKER 0xffda ++#define EOI_MARKER 0xffd9 ++ ++enum { ++ CODA9_JPEG_FORMAT_420, ++ CODA9_JPEG_FORMAT_422, ++ CODA9_JPEG_FORMAT_224, ++ CODA9_JPEG_FORMAT_444, ++ CODA9_JPEG_FORMAT_400, ++}; ++ ++struct coda_huff_tab { ++ u8 luma_dc[16 + 12]; ++ u8 chroma_dc[16 + 12]; ++ u8 luma_ac[16 + 162]; ++ u8 chroma_ac[16 + 162]; ++ ++ /* DC Luma, DC Chroma, AC Luma, AC Chroma */ ++ s16 min[4 * 16]; ++ s16 max[4 * 16]; ++ s8 ptr[4 * 16]; ++}; ++ ++#define CODA9_JPEG_ENC_HUFF_DATA_SIZE (256 + 256 + 16 + 16) ++ ++/* ++ * Typical Huffman tables for 8-bit precision luminance and ++ * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3 ++ */ ++ ++static const unsigned char luma_dc[16 + 12] = { ++ /* bits */ ++ 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ /* values */ ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ 0x08, 0x09, 0x0a, 0x0b, ++}; ++ ++static const unsigned char chroma_dc[16 + 12] = { ++ /* bits */ ++ 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ++ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ++ /* values */ ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ 0x08, 0x09, 0x0a, 0x0b, ++}; ++ ++static const unsigned char luma_ac[16 + 162 + 2] = { ++ /* bits */ ++ 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, ++ 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, ++ /* values */ ++ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, ++ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, ++ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, ++ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, ++ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, ++ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, ++ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, ++ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, ++ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, ++ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, ++ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, ++ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, ++ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, ++ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, ++ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, ++ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, ++ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, ++ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, ++ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, ++ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, ++ 0xf9, 0xfa, /* padded to 32-bit */ ++}; ++ ++static const unsigned char chroma_ac[16 + 162 + 2] = { ++ /* bits */ ++ 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, ++ 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, ++ /* values */ ++ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, ++ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, ++ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, ++ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, ++ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, ++ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, ++ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, ++ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, ++ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, ++ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, ++ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, ++ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, ++ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, ++ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, ++ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, ++ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, ++ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, ++ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, ++ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, ++ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, ++ 0xf9, 0xfa, /* padded to 32-bit */ ++}; ++ ++/* ++ * Quantization tables for luminance and chrominance components in ++ * zig-zag scan order from the Freescale i.MX VPU libraries ++ */ ++ ++static unsigned char luma_q[64] = { ++ 0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05, ++ 0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b, ++ 0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a, ++ 0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++}; ++ ++static unsigned char chroma_q[64] = { ++ 0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10, ++ 0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14, ++ 0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, ++}; ++ ++static const unsigned char width_align[] = { ++ [CODA9_JPEG_FORMAT_420] = 16, ++ [CODA9_JPEG_FORMAT_422] = 16, ++ [CODA9_JPEG_FORMAT_224] = 8, ++ [CODA9_JPEG_FORMAT_444] = 8, ++ [CODA9_JPEG_FORMAT_400] = 8, ++}; ++ ++static const unsigned char height_align[] = { ++ [CODA9_JPEG_FORMAT_420] = 16, ++ [CODA9_JPEG_FORMAT_422] = 8, ++ [CODA9_JPEG_FORMAT_224] = 16, ++ [CODA9_JPEG_FORMAT_444] = 8, ++ [CODA9_JPEG_FORMAT_400] = 8, ++}; ++ ++static int coda9_jpeg_chroma_format(u32 pixfmt) ++{ ++ switch (pixfmt) { ++ case V4L2_PIX_FMT_YUV420: ++ case V4L2_PIX_FMT_NV12: ++ return CODA9_JPEG_FORMAT_420; ++ case V4L2_PIX_FMT_YUV422P: ++ return CODA9_JPEG_FORMAT_422; ++ case V4L2_PIX_FMT_YUV444: ++ return CODA9_JPEG_FORMAT_444; ++ case V4L2_PIX_FMT_GREY: ++ return CODA9_JPEG_FORMAT_400; ++ } ++ return -EINVAL; ++} ++ ++struct coda_memcpy_desc { ++ int offset; ++ const void *src; ++ size_t len; ++}; ++ ++static void coda_memcpy_parabuf(void *parabuf, ++ const struct coda_memcpy_desc *desc) ++{ ++ u32 *dst = parabuf + desc->offset; ++ const u32 *src = desc->src; ++ int len = desc->len / 4; ++ int i; ++ ++ for (i = 0; i < len; i += 2) { ++ dst[i + 1] = swab32(src[i]); ++ dst[i] = swab32(src[i + 1]); ++ } ++} ++ ++int coda_jpeg_write_tables(struct coda_ctx *ctx) ++{ ++ int i; ++ static const struct coda_memcpy_desc huff[8] = { ++ { 0, luma_dc, sizeof(luma_dc) }, ++ { 32, luma_ac, sizeof(luma_ac) }, ++ { 216, chroma_dc, sizeof(chroma_dc) }, ++ { 248, chroma_ac, sizeof(chroma_ac) }, ++ }; ++ struct coda_memcpy_desc qmat[3] = { ++ { 512, ctx->params.jpeg_qmat_tab[0], 64 }, ++ { 576, ctx->params.jpeg_qmat_tab[1], 64 }, ++ { 640, ctx->params.jpeg_qmat_tab[1], 64 }, ++ }; ++ ++ /* Write huffman tables to parameter memory */ ++ for (i = 0; i < ARRAY_SIZE(huff); i++) ++ coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i); ++ ++ /* Write Q-matrix to parameter memory */ ++ for (i = 0; i < ARRAY_SIZE(qmat); i++) ++ coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i); ++ ++ return 0; ++} ++ ++bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb) ++{ ++ void *vaddr = vb2_plane_vaddr(vb, 0); ++ u16 soi, eoi; ++ int len, i; ++ ++ soi = be16_to_cpup((__be16 *)vaddr); ++ if (soi != SOI_MARKER) ++ return false; ++ ++ len = vb2_get_plane_payload(vb, 0); ++ vaddr += len - 2; ++ for (i = 0; i < 32; i++) { ++ eoi = be16_to_cpup((__be16 *)(vaddr - i)); ++ if (eoi == EOI_MARKER) { ++ if (i > 0) ++ vb2_set_plane_payload(vb, 0, len - i); ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num); ++ ++int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb) ++{ ++ struct coda_dev *dev = ctx->dev; ++ u8 *buf = vb2_plane_vaddr(vb, 0); ++ size_t len = vb2_get_plane_payload(vb, 0); ++ struct v4l2_jpeg_scan_header scan_header; ++ struct v4l2_jpeg_reference quantization_tables[4] = { }; ++ struct v4l2_jpeg_reference huffman_tables[4] = { }; ++ struct v4l2_jpeg_header header = { ++ .scan = &scan_header, ++ .quantization_tables = quantization_tables, ++ .huffman_tables = huffman_tables, ++ }; ++ struct coda_q_data *q_data_src; ++ struct coda_huff_tab *huff_tab; ++ int i, j, ret; ++ ++ ret = v4l2_jpeg_parse_header(buf, len, &header); ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, "failed to parse JPEG header: %pe\n", ++ ERR_PTR(ret)); ++ return ret; ++ } ++ ++ ctx->params.jpeg_restart_interval = header.restart_interval; ++ ++ /* check frame header */ ++ if (header.frame.height > ctx->codec->max_h || ++ header.frame.width > ctx->codec->max_w) { ++ v4l2_err(&dev->v4l2_dev, "invalid dimensions: %dx%d\n", ++ header.frame.width, header.frame.height); ++ return -EINVAL; ++ } ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ if (header.frame.height != q_data_src->height || ++ header.frame.width != q_data_src->width) { ++ v4l2_err(&dev->v4l2_dev, ++ "dimensions don't match format: %dx%d\n", ++ header.frame.width, header.frame.height); ++ return -EINVAL; ++ } ++ ++ if (header.frame.num_components != 3) { ++ v4l2_err(&dev->v4l2_dev, ++ "unsupported number of components: %d\n", ++ header.frame.num_components); ++ return -EINVAL; ++ } ++ ++ /* install quantization tables */ ++ if (quantization_tables[3].start) { ++ v4l2_err(&dev->v4l2_dev, ++ "only 3 quantization tables supported\n"); ++ return -EINVAL; ++ } ++ for (i = 0; i < 3; i++) { ++ if (!quantization_tables[i].start) ++ continue; ++ if (quantization_tables[i].length != 64) { ++ v4l2_err(&dev->v4l2_dev, ++ "only 8-bit quantization tables supported\n"); ++ continue; ++ } ++ if (!ctx->params.jpeg_qmat_tab[i]) { ++ ctx->params.jpeg_qmat_tab[i] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[i]) ++ return -ENOMEM; ++ } ++ memcpy(ctx->params.jpeg_qmat_tab[i], ++ quantization_tables[i].start, 64); ++ } ++ ++ /* install Huffman tables */ ++ for (i = 0; i < 4; i++) { ++ if (!huffman_tables[i].start) { ++ v4l2_err(&dev->v4l2_dev, "missing Huffman table\n"); ++ return -EINVAL; ++ } ++ /* AC tables should be between 17 -> 178, DC between 17 -> 28 */ ++ if (huffman_tables[i].length < 17 || ++ huffman_tables[i].length > 178 || ++ ((i & 2) == 0 && huffman_tables[i].length > 28)) { ++ v4l2_err(&dev->v4l2_dev, ++ "invalid Huffman table %d length: %zu\n", ++ i, huffman_tables[i].length); ++ return -EINVAL; ++ } ++ } ++ huff_tab = ctx->params.jpeg_huff_tab; ++ if (!huff_tab) { ++ huff_tab = kzalloc(sizeof(struct coda_huff_tab), GFP_KERNEL); ++ if (!huff_tab) ++ return -ENOMEM; ++ ctx->params.jpeg_huff_tab = huff_tab; ++ } ++ ++ memset(huff_tab, 0, sizeof(*huff_tab)); ++ memcpy(huff_tab->luma_dc, huffman_tables[0].start, huffman_tables[0].length); ++ memcpy(huff_tab->chroma_dc, huffman_tables[1].start, huffman_tables[1].length); ++ memcpy(huff_tab->luma_ac, huffman_tables[2].start, huffman_tables[2].length); ++ memcpy(huff_tab->chroma_ac, huffman_tables[3].start, huffman_tables[3].length); ++ ++ /* check scan header */ ++ for (i = 0; i < scan_header.num_components; i++) { ++ struct v4l2_jpeg_scan_component_spec *scan_component; ++ ++ scan_component = &scan_header.component[i]; ++ for (j = 0; j < header.frame.num_components; j++) { ++ if (header.frame.component[j].component_identifier == ++ scan_component->component_selector) ++ break; ++ } ++ if (j == header.frame.num_components) ++ continue; ++ ++ ctx->params.jpeg_huff_dc_index[j] = ++ scan_component->dc_entropy_coding_table_selector; ++ ctx->params.jpeg_huff_ac_index[j] = ++ scan_component->ac_entropy_coding_table_selector; ++ } ++ ++ /* Generate Huffman table information */ ++ for (i = 0; i < 4; i++) ++ coda9_jpeg_gen_dec_huff_tab(ctx, i); ++ ++ /* start of entropy coded segment */ ++ ctx->jpeg_ecs_offset = header.ecs_offset; ++ ++ switch (header.frame.subsampling) { ++ case V4L2_JPEG_CHROMA_SUBSAMPLING_420: ++ case V4L2_JPEG_CHROMA_SUBSAMPLING_422: ++ ctx->params.jpeg_chroma_subsampling = header.frame.subsampling; ++ break; ++ default: ++ v4l2_err(&dev->v4l2_dev, "chroma subsampling not supported: %d", ++ header.frame.subsampling); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static inline void coda9_jpeg_write_huff_values(struct coda_dev *dev, u8 *bits, ++ int num_values) ++{ ++ s8 *values = (s8 *)(bits + 16); ++ int huff_length, i; ++ ++ for (huff_length = 0, i = 0; i < 16; i++) ++ huff_length += bits[i]; ++ for (i = huff_length; i < num_values; i++) ++ values[i] = -1; ++ for (i = 0; i < num_values; i++) ++ coda_write(dev, (s32)values[i], CODA9_REG_JPEG_HUFF_DATA); ++} ++ ++static void coda9_jpeg_dec_huff_setup(struct coda_ctx *ctx) ++{ ++ struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab; ++ struct coda_dev *dev = ctx->dev; ++ s16 *huff_min = huff_tab->min; ++ s16 *huff_max = huff_tab->max; ++ s8 *huff_ptr = huff_tab->ptr; ++ int i; ++ ++ /* MIN Tables */ ++ coda_write(dev, 0x003, CODA9_REG_JPEG_HUFF_CTRL); ++ coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_ADDR); ++ for (i = 0; i < 4 * 16; i++) ++ coda_write(dev, (s32)huff_min[i], CODA9_REG_JPEG_HUFF_DATA); ++ ++ /* MAX Tables */ ++ coda_write(dev, 0x403, CODA9_REG_JPEG_HUFF_CTRL); ++ coda_write(dev, 0x440, CODA9_REG_JPEG_HUFF_ADDR); ++ for (i = 0; i < 4 * 16; i++) ++ coda_write(dev, (s32)huff_max[i], CODA9_REG_JPEG_HUFF_DATA); ++ ++ /* PTR Tables */ ++ coda_write(dev, 0x803, CODA9_REG_JPEG_HUFF_CTRL); ++ coda_write(dev, 0x880, CODA9_REG_JPEG_HUFF_ADDR); ++ for (i = 0; i < 4 * 16; i++) ++ coda_write(dev, (s32)huff_ptr[i], CODA9_REG_JPEG_HUFF_DATA); ++ ++ /* VAL Tables: DC Luma, DC Chroma, AC Luma, AC Chroma */ ++ coda_write(dev, 0xc03, CODA9_REG_JPEG_HUFF_CTRL); ++ coda9_jpeg_write_huff_values(dev, huff_tab->luma_dc, 12); ++ coda9_jpeg_write_huff_values(dev, huff_tab->chroma_dc, 12); ++ coda9_jpeg_write_huff_values(dev, huff_tab->luma_ac, 162); ++ coda9_jpeg_write_huff_values(dev, huff_tab->chroma_ac, 162); ++ coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_CTRL); ++} ++ ++static inline void coda9_jpeg_write_qmat_tab(struct coda_dev *dev, ++ u8 *qmat, int index) ++{ ++ int i; ++ ++ coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL); ++ for (i = 0; i < 64; i++) ++ coda_write(dev, qmat[i], CODA9_REG_JPEG_QMAT_DATA); ++ coda_write(dev, 0, CODA9_REG_JPEG_QMAT_CTRL); ++} ++ ++static void coda9_jpeg_qmat_setup(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ int *qmat_index = ctx->params.jpeg_qmat_index; ++ u8 **qmat_tab = ctx->params.jpeg_qmat_tab; ++ ++ coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[0]], 0x00); ++ coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[1]], 0x40); ++ coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[2]], 0x80); ++} ++ ++static void coda9_jpeg_dec_bbc_gbu_setup(struct coda_ctx *ctx, ++ struct vb2_buffer *buf, u32 ecs_offset) ++{ ++ struct coda_dev *dev = ctx->dev; ++ int page_ptr, word_ptr, bit_ptr; ++ u32 bbc_base_addr, end_addr; ++ int bbc_cur_pos; ++ int ret, val; ++ ++ bbc_base_addr = vb2_dma_contig_plane_dma_addr(buf, 0); ++ end_addr = bbc_base_addr + vb2_get_plane_payload(buf, 0); ++ ++ page_ptr = ecs_offset / 256; ++ word_ptr = (ecs_offset % 256) / 4; ++ if (page_ptr & 1) ++ word_ptr += 64; ++ bit_ptr = (ecs_offset % 4) * 8; ++ if (word_ptr & 1) ++ bit_ptr += 32; ++ word_ptr &= ~0x1; ++ ++ coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_WR_PTR); ++ coda_write(dev, bbc_base_addr, CODA9_REG_JPEG_BBC_BAS_ADDR); ++ ++ /* Leave 3 256-byte page margin to avoid a BBC interrupt */ ++ coda_write(dev, end_addr + 256 * 3 + 256, CODA9_REG_JPEG_BBC_END_ADDR); ++ val = DIV_ROUND_UP(vb2_plane_size(buf, 0), 256) + 3; ++ coda_write(dev, BIT(31) | val, CODA9_REG_JPEG_BBC_STRM_CTRL); ++ ++ bbc_cur_pos = page_ptr; ++ coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); ++ coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8), ++ CODA9_REG_JPEG_BBC_EXT_ADDR); ++ coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR); ++ coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); ++ coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND); ++ do { ++ ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY); ++ } while (ret == 1); ++ ++ bbc_cur_pos++; ++ coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); ++ coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8), ++ CODA9_REG_JPEG_BBC_EXT_ADDR); ++ coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR); ++ coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); ++ coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND); ++ do { ++ ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY); ++ } while (ret == 1); ++ ++ bbc_cur_pos++; ++ coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); ++ coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_TT_CNT); ++ coda_write(dev, word_ptr, CODA9_REG_JPEG_GBU_WD_PTR); ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); ++ coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); ++ if (page_ptr & 1) { ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBIR); ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBHR); ++ } else { ++ coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR); ++ coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR); ++ } ++ coda_write(dev, 4, CODA9_REG_JPEG_GBU_CTRL); ++ coda_write(dev, bit_ptr, CODA9_REG_JPEG_GBU_FF_RPTR); ++ coda_write(dev, 3, CODA9_REG_JPEG_GBU_CTRL); ++} ++ ++static const int bus_req_num[] = { ++ [CODA9_JPEG_FORMAT_420] = 2, ++ [CODA9_JPEG_FORMAT_422] = 3, ++ [CODA9_JPEG_FORMAT_224] = 3, ++ [CODA9_JPEG_FORMAT_444] = 4, ++ [CODA9_JPEG_FORMAT_400] = 4, ++}; ++ ++#define MCU_INFO(mcu_block_num, comp_num, comp0_info, comp1_info, comp2_info) \ ++ (((mcu_block_num) << CODA9_JPEG_MCU_BLOCK_NUM_OFFSET) | \ ++ ((comp_num) << CODA9_JPEG_COMP_NUM_OFFSET) | \ ++ ((comp0_info) << CODA9_JPEG_COMP0_INFO_OFFSET) | \ ++ ((comp1_info) << CODA9_JPEG_COMP1_INFO_OFFSET) | \ ++ ((comp2_info) << CODA9_JPEG_COMP2_INFO_OFFSET)) ++ ++static const u32 mcu_info[] = { ++ [CODA9_JPEG_FORMAT_420] = MCU_INFO(6, 3, 10, 5, 5), ++ [CODA9_JPEG_FORMAT_422] = MCU_INFO(4, 3, 9, 5, 5), ++ [CODA9_JPEG_FORMAT_224] = MCU_INFO(4, 3, 6, 5, 5), ++ [CODA9_JPEG_FORMAT_444] = MCU_INFO(3, 3, 5, 5, 5), ++ [CODA9_JPEG_FORMAT_400] = MCU_INFO(1, 1, 5, 0, 0), ++}; ++ ++/* ++ * Convert Huffman table specifcations to tables of codes and code lengths. ++ * For reference, see JPEG ITU-T.81 (ISO/IEC 10918-1) [1] ++ * ++ * [1] https://www.w3.org/Graphics/JPEG/itu-t81.pdf ++ */ ++static int coda9_jpeg_gen_enc_huff_tab(struct coda_ctx *ctx, int tab_num, ++ int *ehufsi, int *ehufco) ++{ ++ int i, j, k, lastk, si, code, maxsymbol; ++ const u8 *bits, *huffval; ++ struct { ++ int size[256]; ++ int code[256]; ++ } *huff; ++ static const unsigned char *huff_tabs[4] = { ++ luma_dc, luma_ac, chroma_dc, chroma_ac, ++ }; ++ int ret = -EINVAL; ++ ++ huff = kzalloc(sizeof(*huff), GFP_KERNEL); ++ if (!huff) ++ return -ENOMEM; ++ ++ bits = huff_tabs[tab_num]; ++ huffval = huff_tabs[tab_num] + 16; ++ ++ maxsymbol = tab_num & 1 ? 256 : 16; ++ ++ /* Figure C.1 - Generation of table of Huffman code sizes */ ++ k = 0; ++ for (i = 1; i <= 16; i++) { ++ j = bits[i - 1]; ++ if (k + j > maxsymbol) ++ goto out; ++ while (j--) ++ huff->size[k++] = i; ++ } ++ lastk = k; ++ ++ /* Figure C.2 - Generation of table of Huffman codes */ ++ k = 0; ++ code = 0; ++ si = huff->size[0]; ++ while (k < lastk) { ++ while (huff->size[k] == si) { ++ huff->code[k++] = code; ++ code++; ++ } ++ if (code >= (1 << si)) ++ goto out; ++ code <<= 1; ++ si++; ++ } ++ ++ /* Figure C.3 - Ordering procedure for encoding procedure code tables */ ++ for (k = 0; k < lastk; k++) { ++ i = huffval[k]; ++ if (i >= maxsymbol || ehufsi[i]) ++ goto out; ++ ehufco[i] = huff->code[k]; ++ ehufsi[i] = huff->size[k]; ++ } ++ ++ ret = 0; ++out: ++ kfree(huff); ++ return ret; ++} ++ ++#define DC_TABLE_INDEX0 0 ++#define AC_TABLE_INDEX0 1 ++#define DC_TABLE_INDEX1 2 ++#define AC_TABLE_INDEX1 3 ++ ++static u8 *coda9_jpeg_get_huff_bits(struct coda_ctx *ctx, int tab_num) ++{ ++ struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab; ++ ++ if (!huff_tab) ++ return NULL; ++ ++ switch (tab_num) { ++ case DC_TABLE_INDEX0: return huff_tab->luma_dc; ++ case AC_TABLE_INDEX0: return huff_tab->luma_ac; ++ case DC_TABLE_INDEX1: return huff_tab->chroma_dc; ++ case AC_TABLE_INDEX1: return huff_tab->chroma_ac; ++ } ++ ++ return NULL; ++} ++ ++static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num) ++{ ++ int ptr_cnt = 0, huff_code = 0, zero_flag = 0, data_flag = 0; ++ u8 *huff_bits; ++ s16 *huff_max; ++ s16 *huff_min; ++ s8 *huff_ptr; ++ int ofs; ++ int i; ++ ++ huff_bits = coda9_jpeg_get_huff_bits(ctx, tab_num); ++ if (!huff_bits) ++ return -EINVAL; ++ ++ /* DC/AC Luma, DC/AC Chroma -> DC Luma/Chroma, AC Luma/Chroma */ ++ ofs = ((tab_num & 1) << 1) | ((tab_num >> 1) & 1); ++ ofs *= 16; ++ ++ huff_ptr = ctx->params.jpeg_huff_tab->ptr + ofs; ++ huff_max = ctx->params.jpeg_huff_tab->max + ofs; ++ huff_min = ctx->params.jpeg_huff_tab->min + ofs; ++ ++ for (i = 0; i < 16; i++) { ++ if (huff_bits[i]) { ++ huff_ptr[i] = ptr_cnt; ++ ptr_cnt += huff_bits[i]; ++ huff_min[i] = huff_code; ++ huff_max[i] = huff_code + (huff_bits[i] - 1); ++ data_flag = 1; ++ zero_flag = 0; ++ } else { ++ huff_ptr[i] = -1; ++ huff_min[i] = -1; ++ huff_max[i] = -1; ++ zero_flag = 1; ++ } ++ ++ if (data_flag == 1) { ++ if (zero_flag == 1) ++ huff_code <<= 1; ++ else ++ huff_code = (huff_max[i] + 1) << 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static int coda9_jpeg_load_huff_tab(struct coda_ctx *ctx) ++{ ++ struct { ++ int size[4][256]; ++ int code[4][256]; ++ } *huff; ++ u32 *huff_data; ++ int i, j; ++ int ret; ++ ++ huff = kzalloc(sizeof(*huff), GFP_KERNEL); ++ if (!huff) ++ return -ENOMEM; ++ ++ /* Generate all four (luma/chroma DC/AC) code/size lookup tables */ ++ for (i = 0; i < 4; i++) { ++ ret = coda9_jpeg_gen_enc_huff_tab(ctx, i, huff->size[i], ++ huff->code[i]); ++ if (ret) ++ goto out; ++ } ++ ++ if (!ctx->params.jpeg_huff_data) { ++ ctx->params.jpeg_huff_data = ++ kzalloc(sizeof(u32) * CODA9_JPEG_ENC_HUFF_DATA_SIZE, ++ GFP_KERNEL); ++ if (!ctx->params.jpeg_huff_data) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ } ++ huff_data = ctx->params.jpeg_huff_data; ++ ++ for (j = 0; j < 4; j++) { ++ /* Store Huffman lookup tables in AC0, AC1, DC0, DC1 order */ ++ int t = (j == 0) ? AC_TABLE_INDEX0 : ++ (j == 1) ? AC_TABLE_INDEX1 : ++ (j == 2) ? DC_TABLE_INDEX0 : ++ DC_TABLE_INDEX1; ++ /* DC tables only have 16 entries */ ++ int len = (j < 2) ? 256 : 16; ++ ++ for (i = 0; i < len; i++) { ++ if (huff->size[t][i] == 0 && huff->code[t][i] == 0) ++ *(huff_data++) = 0; ++ else ++ *(huff_data++) = ++ ((huff->size[t][i] - 1) << 16) | ++ huff->code[t][i]; ++ } ++ } ++ ++ ret = 0; ++out: ++ kfree(huff); ++ return ret; ++} ++ ++static void coda9_jpeg_write_huff_tab(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ u32 *huff_data = ctx->params.jpeg_huff_data; ++ int i; ++ ++ /* Write Huffman size/code lookup tables in AC0, AC1, DC0, DC1 order */ ++ coda_write(dev, 0x3, CODA9_REG_JPEG_HUFF_CTRL); ++ for (i = 0; i < CODA9_JPEG_ENC_HUFF_DATA_SIZE; i++) ++ coda_write(dev, *(huff_data++), CODA9_REG_JPEG_HUFF_DATA); ++ coda_write(dev, 0x0, CODA9_REG_JPEG_HUFF_CTRL); ++} ++ ++static inline void coda9_jpeg_write_qmat_quotients(struct coda_dev *dev, ++ u8 *qmat, int index) ++{ ++ int i; ++ ++ coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL); ++ for (i = 0; i < 64; i++) ++ coda_write(dev, 0x80000 / qmat[i], CODA9_REG_JPEG_QMAT_DATA); ++ coda_write(dev, index, CODA9_REG_JPEG_QMAT_CTRL); ++} ++ ++static void coda9_jpeg_load_qmat_tab(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ u8 *luma_tab; ++ u8 *chroma_tab; ++ ++ luma_tab = ctx->params.jpeg_qmat_tab[0]; ++ if (!luma_tab) ++ luma_tab = luma_q; ++ ++ chroma_tab = ctx->params.jpeg_qmat_tab[1]; ++ if (!chroma_tab) ++ chroma_tab = chroma_q; ++ ++ coda9_jpeg_write_qmat_quotients(dev, luma_tab, 0x00); ++ coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x40); ++ coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x80); ++} ++ ++struct coda_jpeg_stream { ++ u8 *curr; ++ u8 *end; ++}; ++ ++static inline int coda_jpeg_put_byte(u8 byte, struct coda_jpeg_stream *stream) ++{ ++ if (stream->curr >= stream->end) ++ return -EINVAL; ++ ++ *stream->curr++ = byte; ++ ++ return 0; ++} ++ ++static inline int coda_jpeg_put_word(u16 word, struct coda_jpeg_stream *stream) ++{ ++ if (stream->curr + sizeof(__be16) > stream->end) ++ return -EINVAL; ++ ++ put_unaligned_be16(word, stream->curr); ++ stream->curr += sizeof(__be16); ++ ++ return 0; ++} ++ ++static int coda_jpeg_put_table(u16 marker, u8 index, const u8 *table, ++ size_t len, struct coda_jpeg_stream *stream) ++{ ++ int i, ret; ++ ++ ret = coda_jpeg_put_word(marker, stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_word(3 + len, stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_byte(index, stream); ++ for (i = 0; i < len && ret == 0; i++) ++ ret = coda_jpeg_put_byte(table[i], stream); ++ ++ return ret; ++} ++ ++static int coda_jpeg_define_quantization_table(struct coda_ctx *ctx, u8 index, ++ struct coda_jpeg_stream *stream) ++{ ++ return coda_jpeg_put_table(DQT_MARKER, index, ++ ctx->params.jpeg_qmat_tab[index], 64, ++ stream); ++} ++ ++static int coda_jpeg_define_huffman_table(u8 index, const u8 *table, size_t len, ++ struct coda_jpeg_stream *stream) ++{ ++ return coda_jpeg_put_table(DHT_MARKER, index, table, len, stream); ++} ++ ++static int coda9_jpeg_encode_header(struct coda_ctx *ctx, int len, u8 *buf) ++{ ++ struct coda_jpeg_stream stream = { buf, buf + len }; ++ struct coda_q_data *q_data_src; ++ int chroma_format, comp_num; ++ int i, ret, pad; ++ ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc); ++ if (chroma_format < 0) ++ return 0; ++ ++ /* Start Of Image */ ++ ret = coda_jpeg_put_word(SOI_MARKER, &stream); ++ if (ret < 0) ++ return ret; ++ ++ /* Define Restart Interval */ ++ if (ctx->params.jpeg_restart_interval) { ++ ret = coda_jpeg_put_word(DRI_MARKER, &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_word(4, &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_word(ctx->params.jpeg_restart_interval, ++ &stream); ++ if (ret < 0) ++ return ret; ++ } ++ ++ /* Define Quantization Tables */ ++ ret = coda_jpeg_define_quantization_table(ctx, 0x00, &stream); ++ if (ret < 0) ++ return ret; ++ if (chroma_format != CODA9_JPEG_FORMAT_400) { ++ ret = coda_jpeg_define_quantization_table(ctx, 0x01, &stream); ++ if (ret < 0) ++ return ret; ++ } ++ ++ /* Define Huffman Tables */ ++ ret = coda_jpeg_define_huffman_table(0x00, luma_dc, 16 + 12, &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_define_huffman_table(0x10, luma_ac, 16 + 162, &stream); ++ if (ret < 0) ++ return ret; ++ if (chroma_format != CODA9_JPEG_FORMAT_400) { ++ ret = coda_jpeg_define_huffman_table(0x01, chroma_dc, 16 + 12, ++ &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_define_huffman_table(0x11, chroma_ac, 16 + 162, ++ &stream); ++ if (ret < 0) ++ return ret; ++ } ++ ++ /* Start Of Frame */ ++ ret = coda_jpeg_put_word(SOF_MARKER, &stream); ++ if (ret < 0) ++ return ret; ++ comp_num = (chroma_format == CODA9_JPEG_FORMAT_400) ? 1 : 3; ++ ret = coda_jpeg_put_word(8 + comp_num * 3, &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_byte(0x08, &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_word(q_data_src->height, &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_word(q_data_src->width, &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_byte(comp_num, &stream); ++ if (ret < 0) ++ return ret; ++ for (i = 0; i < comp_num; i++) { ++ static unsigned char subsampling[5][3] = { ++ [CODA9_JPEG_FORMAT_420] = { 0x22, 0x11, 0x11 }, ++ [CODA9_JPEG_FORMAT_422] = { 0x21, 0x11, 0x11 }, ++ [CODA9_JPEG_FORMAT_224] = { 0x12, 0x11, 0x11 }, ++ [CODA9_JPEG_FORMAT_444] = { 0x11, 0x11, 0x11 }, ++ [CODA9_JPEG_FORMAT_400] = { 0x11 }, ++ }; ++ ++ /* Component identifier, matches SOS */ ++ ret = coda_jpeg_put_byte(i + 1, &stream); ++ if (ret < 0) ++ return ret; ++ ret = coda_jpeg_put_byte(subsampling[chroma_format][i], ++ &stream); ++ if (ret < 0) ++ return ret; ++ /* Chroma table index */ ++ ret = coda_jpeg_put_byte((i == 0) ? 0 : 1, &stream); ++ if (ret < 0) ++ return ret; ++ } ++ ++ /* Pad to multiple of 8 bytes */ ++ pad = (stream.curr - buf) % 8; ++ if (pad) { ++ pad = 8 - pad; ++ while (pad--) { ++ ret = coda_jpeg_put_byte(0x00, &stream); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ ++ return stream.curr - buf; ++} ++ ++/* ++ * Scale quantization table using nonlinear scaling factor ++ * u8 qtab[64], scale [50,190] ++ */ ++static void coda_scale_quant_table(u8 *q_tab, int scale) ++{ ++ unsigned int temp; ++ int i; ++ ++ for (i = 0; i < 64; i++) { ++ temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100); ++ if (temp <= 0) ++ temp = 1; ++ if (temp > 255) ++ temp = 255; ++ q_tab[i] = (unsigned char)temp; ++ } ++} ++ ++void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality) ++{ ++ unsigned int scale; ++ ++ ctx->params.jpeg_quality = quality; ++ ++ /* Clip quality setting to [5,100] interval */ ++ if (quality > 100) ++ quality = 100; ++ if (quality < 5) ++ quality = 5; ++ ++ /* ++ * Non-linear scaling factor: ++ * [5,50] -> [1000..100], [51,100] -> [98..0] ++ */ ++ if (quality < 50) ++ scale = 5000 / quality; ++ else ++ scale = 200 - 2 * quality; ++ ++ if (ctx->params.jpeg_qmat_tab[0]) { ++ memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64); ++ coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale); ++ } ++ if (ctx->params.jpeg_qmat_tab[1]) { ++ memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64); ++ coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale); ++ } ++} ++ ++/* ++ * Encoder context operations ++ */ ++ ++static int coda9_jpeg_start_encoding(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ int ret; ++ ++ ret = coda9_jpeg_load_huff_tab(ctx); ++ if (ret < 0) { ++ v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n"); ++ return ret; ++ } ++ if (!ctx->params.jpeg_qmat_tab[0]) { ++ ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[0]) ++ return -ENOMEM; ++ } ++ if (!ctx->params.jpeg_qmat_tab[1]) { ++ ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[1]) ++ return -ENOMEM; ++ } ++ coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); ++ ++ return 0; ++} ++ ++static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx) ++{ ++ struct coda_q_data *q_data_src; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ struct coda_dev *dev = ctx->dev; ++ u32 start_addr, end_addr; ++ u16 aligned_width, aligned_height; ++ bool chroma_interleave; ++ int chroma_format; ++ int header_len; ++ int ret; ++ ktime_t timeout; ++ ++ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ ++ if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0) ++ vb2_set_plane_payload(&src_buf->vb2_buf, 0, ++ vb2_plane_size(&src_buf->vb2_buf, 0)); ++ ++ src_buf->sequence = ctx->osequence; ++ dst_buf->sequence = ctx->osequence; ++ ctx->osequence++; ++ ++ src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; ++ src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME; ++ ++ coda_set_gdi_regs(ctx); ++ ++ start_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); ++ end_addr = start_addr + vb2_plane_size(&dst_buf->vb2_buf, 0); ++ ++ chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc); ++ if (chroma_format < 0) ++ return chroma_format; ++ ++ /* Round image dimensions to multiple of MCU size */ ++ aligned_width = round_up(q_data_src->width, width_align[chroma_format]); ++ aligned_height = round_up(q_data_src->height, ++ height_align[chroma_format]); ++ if (aligned_width != q_data_src->bytesperline) { ++ v4l2_err(&dev->v4l2_dev, "wrong stride: %d instead of %d\n", ++ aligned_width, q_data_src->bytesperline); ++ } ++ ++ header_len = ++ coda9_jpeg_encode_header(ctx, ++ vb2_plane_size(&dst_buf->vb2_buf, 0), ++ vb2_plane_vaddr(&dst_buf->vb2_buf, 0)); ++ if (header_len < 0) ++ return header_len; ++ ++ coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_BAS_ADDR); ++ coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_END_ADDR); ++ coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_WR_PTR); ++ coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_RD_PTR); ++ coda_write(dev, 0, CODA9_REG_JPEG_BBC_CUR_POS); ++ /* 64 words per 256-byte page */ ++ coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); ++ coda_write(dev, start_addr, CODA9_REG_JPEG_BBC_EXT_ADDR); ++ coda_write(dev, 0, CODA9_REG_JPEG_BBC_INT_ADDR); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR); ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR); ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); ++ coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256), ++ CODA9_REG_JPEG_BBC_STRM_CTRL); ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL); ++ coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR); ++ coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); ++ coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR); ++ coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR); ++ ++ chroma_interleave = (q_data_src->fourcc == V4L2_PIX_FMT_NV12); ++ coda_write(dev, CODA9_JPEG_PIC_CTRL_TC_DIRECTION | ++ CODA9_JPEG_PIC_CTRL_ENCODER_EN, CODA9_REG_JPEG_PIC_CTRL); ++ coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO); ++ coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG); ++ coda_write(dev, ctx->params.jpeg_restart_interval, ++ CODA9_REG_JPEG_RST_INTVAL); ++ coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL); ++ ++ coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO); ++ ++ coda9_jpeg_write_huff_tab(ctx); ++ coda9_jpeg_load_qmat_tab(ctx); ++ ++ if (ctx->params.rot_mode & CODA_ROT_90) { ++ aligned_width = aligned_height; ++ aligned_height = q_data_src->bytesperline; ++ if (chroma_format == CODA9_JPEG_FORMAT_422) ++ chroma_format = CODA9_JPEG_FORMAT_224; ++ else if (chroma_format == CODA9_JPEG_FORMAT_224) ++ chroma_format = CODA9_JPEG_FORMAT_422; ++ } ++ /* These need to be multiples of MCU size */ ++ coda_write(dev, aligned_width << 16 | aligned_height, ++ CODA9_REG_JPEG_PIC_SIZE); ++ coda_write(dev, ctx->params.rot_mode ? ++ (CODA_ROT_MIR_ENABLE | ctx->params.rot_mode) : 0, ++ CODA9_REG_JPEG_ROT_INFO); ++ ++ coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO); ++ ++ coda_write(dev, 1, CODA9_GDI_CONTROL); ++ timeout = ktime_add_us(ktime_get(), 100000); ++ do { ++ ret = coda_read(dev, CODA9_GDI_STATUS); ++ if (ktime_compare(ktime_get(), timeout) > 0) { ++ v4l2_err(&dev->v4l2_dev, "timeout waiting for GDI\n"); ++ return -ETIMEDOUT; ++ } ++ } while (!ret); ++ ++ coda_write(dev, (chroma_format << 17) | (chroma_interleave << 16) | ++ q_data_src->bytesperline, CODA9_GDI_INFO_CONTROL); ++ /* The content of this register seems to be irrelevant: */ ++ coda_write(dev, aligned_width << 16 | aligned_height, ++ CODA9_GDI_INFO_PIC_SIZE); ++ ++ coda_write_base(ctx, q_data_src, src_buf, CODA9_GDI_INFO_BASE_Y); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00); ++ coda_write(dev, 0, CODA9_GDI_CONTROL); ++ coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST); ++ ++ coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); ++ coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); ++ ++ trace_coda_jpeg_run(ctx, src_buf); ++ ++ coda_write(dev, 1, CODA9_REG_JPEG_PIC_START); ++ ++ return 0; ++} ++ ++static void coda9_jpeg_finish_encode(struct coda_ctx *ctx) ++{ ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ struct coda_dev *dev = ctx->dev; ++ u32 wr_ptr, start_ptr; ++ u32 err_mb; ++ ++ if (ctx->aborting) { ++ coda_write(ctx->dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); ++ return; ++ } ++ ++ /* ++ * Lock to make sure that an encoder stop command running in parallel ++ * will either already have marked src_buf as last, or it will wake up ++ * the capture queue after the buffers are returned. ++ */ ++ mutex_lock(&ctx->wakeup_mutex); ++ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); ++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); ++ ++ trace_coda_jpeg_done(ctx, dst_buf); ++ ++ /* ++ * Set plane payload to the number of bytes written out ++ * by the JPEG processing unit ++ */ ++ start_ptr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); ++ wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr); ++ ++ err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); ++ if (err_mb) ++ coda_dbg(1, ctx, "ERRMB: 0x%x\n", err_mb); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); ++ ++ dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST); ++ dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; ++ dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST; ++ ++ v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); ++ ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR : ++ VB2_BUF_STATE_DONE); ++ mutex_unlock(&ctx->wakeup_mutex); ++ ++ coda_dbg(1, ctx, "job finished: encoded frame (%u)%s\n", ++ dst_buf->sequence, ++ (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : ""); ++ ++ /* ++ * Reset JPEG processing unit after each encode run to work ++ * around hangups when switching context between encoder and ++ * decoder. ++ */ ++ coda_hw_reset(ctx); ++} ++ ++static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ u32 end_addr, wr_ptr; ++ ++ /* Handle missing BBC overflow interrupt via timeout */ ++ end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR); ++ wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); ++ if (wr_ptr >= end_addr - 256) { ++ v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n"); ++ coda9_jpeg_finish_encode(ctx); ++ return; ++ } ++ ++ coda_hw_reset(ctx); ++} ++ ++static void coda9_jpeg_release(struct coda_ctx *ctx) ++{ ++ int i; ++ ++ if (ctx->params.jpeg_qmat_tab[0] == luma_q) ++ ctx->params.jpeg_qmat_tab[0] = NULL; ++ if (ctx->params.jpeg_qmat_tab[1] == chroma_q) ++ ctx->params.jpeg_qmat_tab[1] = NULL; ++ for (i = 0; i < 3; i++) ++ kfree(ctx->params.jpeg_qmat_tab[i]); ++ kfree(ctx->params.jpeg_huff_data); ++ kfree(ctx->params.jpeg_huff_tab); ++} ++ ++const struct coda_context_ops coda9_jpeg_encode_ops = { ++ .queue_init = coda_encoder_queue_init, ++ .start_streaming = coda9_jpeg_start_encoding, ++ .prepare_run = coda9_jpeg_prepare_encode, ++ .finish_run = coda9_jpeg_finish_encode, ++ .run_timeout = coda9_jpeg_encode_timeout, ++ .release = coda9_jpeg_release, ++}; ++ ++/* ++ * Decoder context operations ++ */ ++ ++static int coda9_jpeg_start_decoding(struct coda_ctx *ctx) ++{ ++ ctx->params.jpeg_qmat_index[0] = 0; ++ ctx->params.jpeg_qmat_index[1] = 1; ++ ctx->params.jpeg_qmat_index[2] = 1; ++ ctx->params.jpeg_qmat_tab[0] = luma_q; ++ ctx->params.jpeg_qmat_tab[1] = chroma_q; ++ /* nothing more to do here */ ++ ++ /* TODO: we could already scan the first header to get the chroma ++ * format. ++ */ ++ ++ return 0; ++} ++ ++static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ int aligned_width, aligned_height; ++ int chroma_format; ++ int ret; ++ u32 val, dst_fourcc; ++ struct coda_q_data *q_data_src, *q_data_dst; ++ struct vb2_v4l2_buffer *src_buf, *dst_buf; ++ int chroma_interleave; ++ int scl_hor_mode, scl_ver_mode; ++ ++ src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); ++ dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ++ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ dst_fourcc = q_data_dst->fourcc; ++ ++ scl_hor_mode = coda_jpeg_scale(q_data_src->width, q_data_dst->width); ++ scl_ver_mode = coda_jpeg_scale(q_data_src->height, q_data_dst->height); ++ ++ if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0) ++ vb2_set_plane_payload(&src_buf->vb2_buf, 0, ++ vb2_plane_size(&src_buf->vb2_buf, 0)); ++ ++ chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc); ++ if (chroma_format < 0) ++ return chroma_format; ++ ++ ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf); ++ if (ret < 0) { ++ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); ++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); ++ ++ return ret; ++ } ++ ++ /* Round image dimensions to multiple of MCU size */ ++ aligned_width = round_up(q_data_src->width, width_align[chroma_format]); ++ aligned_height = round_up(q_data_src->height, height_align[chroma_format]); ++ if (aligned_width != q_data_dst->bytesperline) { ++ v4l2_err(&dev->v4l2_dev, "stride mismatch: %d != %d\n", ++ aligned_width, q_data_dst->bytesperline); ++ } ++ ++ coda_set_gdi_regs(ctx); ++ ++ val = ctx->params.jpeg_huff_ac_index[0] << 12 | ++ ctx->params.jpeg_huff_ac_index[1] << 11 | ++ ctx->params.jpeg_huff_ac_index[2] << 10 | ++ ctx->params.jpeg_huff_dc_index[0] << 9 | ++ ctx->params.jpeg_huff_dc_index[1] << 8 | ++ ctx->params.jpeg_huff_dc_index[2] << 7; ++ if (ctx->params.jpeg_huff_tab) ++ val |= CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN; ++ coda_write(dev, val, CODA9_REG_JPEG_PIC_CTRL); ++ ++ coda_write(dev, aligned_width << 16 | aligned_height, ++ CODA9_REG_JPEG_PIC_SIZE); ++ ++ chroma_interleave = (dst_fourcc == V4L2_PIX_FMT_NV12); ++ coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO); ++ coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO); ++ coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO); ++ if (scl_hor_mode || scl_ver_mode) ++ val = CODA9_JPEG_SCL_ENABLE | (scl_hor_mode << 2) | scl_ver_mode; ++ else ++ val = 0; ++ coda_write(dev, val, CODA9_REG_JPEG_SCL_INFO); ++ coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG); ++ coda_write(dev, ctx->params.jpeg_restart_interval, ++ CODA9_REG_JPEG_RST_INTVAL); ++ ++ if (ctx->params.jpeg_huff_tab) ++ coda9_jpeg_dec_huff_setup(ctx); ++ ++ coda9_jpeg_qmat_setup(ctx); ++ ++ coda9_jpeg_dec_bbc_gbu_setup(ctx, &src_buf->vb2_buf, ++ ctx->jpeg_ecs_offset); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_RST_INDEX); ++ coda_write(dev, 0, CODA9_REG_JPEG_RST_COUNT); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_Y); ++ coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CB); ++ coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CR); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO); ++ ++ coda_write(dev, 1, CODA9_GDI_CONTROL); ++ do { ++ ret = coda_read(dev, CODA9_GDI_STATUS); ++ } while (!ret); ++ ++ val = (chroma_format << 17) | (chroma_interleave << 16) | ++ q_data_dst->bytesperline; ++ if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) ++ val |= 3 << 20; ++ coda_write(dev, val, CODA9_GDI_INFO_CONTROL); ++ ++ coda_write(dev, aligned_width << 16 | aligned_height, ++ CODA9_GDI_INFO_PIC_SIZE); ++ ++ coda_write_base(ctx, q_data_dst, dst_buf, CODA9_GDI_INFO_BASE_Y); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00); ++ coda_write(dev, 0, CODA9_GDI_CONTROL); ++ coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST); ++ ++ trace_coda_jpeg_run(ctx, src_buf); ++ ++ coda_write(dev, 1, CODA9_REG_JPEG_PIC_START); ++ ++ return 0; ++} ++ ++static void coda9_jpeg_finish_decode(struct coda_ctx *ctx) ++{ ++ struct coda_dev *dev = ctx->dev; ++ struct vb2_v4l2_buffer *dst_buf, *src_buf; ++ struct coda_q_data *q_data_dst; ++ u32 err_mb; ++ ++ err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); ++ if (err_mb) ++ v4l2_err(&dev->v4l2_dev, "ERRMB: 0x%x\n", err_mb); ++ ++ coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); ++ ++ /* ++ * Lock to make sure that a decoder stop command running in parallel ++ * will either already have marked src_buf as last, or it will wake up ++ * the capture queue after the buffers are returned. ++ */ ++ mutex_lock(&ctx->wakeup_mutex); ++ src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); ++ dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); ++ dst_buf->sequence = ctx->osequence++; ++ ++ trace_coda_jpeg_done(ctx, dst_buf); ++ ++ dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST); ++ dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; ++ dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST; ++ ++ v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); ++ ++ q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, q_data_dst->sizeimage); ++ ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR : ++ VB2_BUF_STATE_DONE); ++ ++ mutex_unlock(&ctx->wakeup_mutex); ++ ++ coda_dbg(1, ctx, "job finished: decoded frame (%u)%s\n", ++ dst_buf->sequence, ++ (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : ""); ++ ++ /* ++ * Reset JPEG processing unit after each decode run to work ++ * around hangups when switching context between encoder and ++ * decoder. ++ */ ++ coda_hw_reset(ctx); ++} ++ ++const struct coda_context_ops coda9_jpeg_decode_ops = { ++ .queue_init = coda_encoder_queue_init, /* non-bitstream operation */ ++ .start_streaming = coda9_jpeg_start_decoding, ++ .prepare_run = coda9_jpeg_prepare_decode, ++ .finish_run = coda9_jpeg_finish_decode, ++ .release = coda9_jpeg_release, ++}; ++ ++irqreturn_t coda9_jpeg_irq_handler(int irq, void *data) ++{ ++ struct coda_dev *dev = data; ++ struct coda_ctx *ctx; ++ int status; ++ int err_mb; ++ ++ status = coda_read(dev, CODA9_REG_JPEG_PIC_STATUS); ++ if (status == 0) ++ return IRQ_HANDLED; ++ coda_write(dev, status, CODA9_REG_JPEG_PIC_STATUS); ++ ++ if (status & CODA9_JPEG_STATUS_OVERFLOW) ++ v4l2_err(&dev->v4l2_dev, "JPEG overflow\n"); ++ ++ if (status & CODA9_JPEG_STATUS_BBC_INT) ++ v4l2_err(&dev->v4l2_dev, "JPEG BBC interrupt\n"); ++ ++ if (status & CODA9_JPEG_STATUS_ERROR) { ++ v4l2_err(&dev->v4l2_dev, "JPEG error\n"); ++ ++ err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); ++ if (err_mb) { ++ v4l2_err(&dev->v4l2_dev, ++ "ERRMB: 0x%x: rst idx %d, mcu pos (%d,%d)\n", ++ err_mb, err_mb >> 24, (err_mb >> 12) & 0xfff, ++ err_mb & 0xfff); ++ } ++ } ++ ++ ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); ++ if (!ctx) { ++ v4l2_err(&dev->v4l2_dev, ++ "Instance released before the end of transaction\n"); ++ mutex_unlock(&dev->coda_mutex); ++ return IRQ_HANDLED; ++ } ++ ++ complete(&ctx->completion); ++ ++ return IRQ_HANDLED; ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-mpeg2.c b/drivers/media/platform/chips-media/coda/coda-mpeg2.c +--- a/drivers/media/platform/chips-media/coda/coda-mpeg2.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda-mpeg2.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,87 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Coda multi-standard codec IP - MPEG-2 helper functions ++ * ++ * Copyright (C) 2019 Pengutronix, Philipp Zabel ++ */ ++ ++#include ++#include ++#include "coda.h" ++ ++int coda_mpeg2_profile(int profile_idc) ++{ ++ switch (profile_idc) { ++ case 5: ++ return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE; ++ case 4: ++ return V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN; ++ case 3: ++ return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE; ++ case 2: ++ return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE; ++ case 1: ++ return V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH; ++ default: ++ return -EINVAL; ++ } ++} ++ ++int coda_mpeg2_level(int level_idc) ++{ ++ switch (level_idc) { ++ case 10: ++ return V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW; ++ case 8: ++ return V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN; ++ case 6: ++ return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440; ++ case 4: ++ return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH; ++ default: ++ return -EINVAL; ++ } ++} ++ ++/* ++ * Check if the buffer starts with the MPEG-2 sequence header (with or without ++ * quantization matrix) and extension header, for example: ++ * ++ * 00 00 01 b3 2d 01 e0 34 08 8b a3 81 ++ * 10 11 11 12 12 12 13 13 13 13 14 14 14 14 14 15 ++ * 15 15 15 15 15 16 16 16 16 16 16 16 17 17 17 17 ++ * 17 17 17 17 18 18 18 19 18 18 18 19 1a 1a 1a 1a ++ * 19 1b 1b 1b 1b 1b 1c 1c 1c 1c 1e 1e 1e 1f 1f 21 ++ * 00 00 01 b5 14 8a 00 01 00 00 ++ * ++ * or: ++ * ++ * 00 00 01 b3 08 00 40 15 ff ff e0 28 ++ * 00 00 01 b5 14 8a 00 01 00 00 ++ * ++ * Returns the detected header size in bytes or 0. ++ */ ++u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size) ++{ ++ static const u8 sequence_header_start[4] = { 0x00, 0x00, 0x01, 0xb3 }; ++ static const union { ++ u8 extension_start[4]; ++ u8 start_code_prefix[3]; ++ } u = { { 0x00, 0x00, 0x01, 0xb5 } }; ++ ++ if (size < 22 || ++ memcmp(buf, sequence_header_start, 4) != 0) ++ return 0; ++ ++ if ((size == 22 || ++ (size >= 25 && memcmp(buf + 22, u.start_code_prefix, 3) == 0)) && ++ memcmp(buf + 12, u.extension_start, 4) == 0) ++ return 22; ++ ++ if ((size == 86 || ++ (size > 89 && memcmp(buf + 86, u.start_code_prefix, 3) == 0)) && ++ memcmp(buf + 76, u.extension_start, 4) == 0) ++ return 86; ++ ++ return 0; ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-mpeg4.c b/drivers/media/platform/chips-media/coda/coda-mpeg4.c +--- a/drivers/media/platform/chips-media/coda/coda-mpeg4.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda-mpeg4.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,87 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Coda multi-standard codec IP - MPEG-4 helper functions ++ * ++ * Copyright (C) 2019 Pengutronix, Philipp Zabel ++ */ ++ ++#include ++#include ++ ++#include "coda.h" ++ ++int coda_mpeg4_profile(int profile_idc) ++{ ++ switch (profile_idc) { ++ case 0: ++ return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE; ++ case 15: ++ return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE; ++ case 2: ++ return V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE; ++ case 1: ++ return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE; ++ case 11: ++ return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY; ++ default: ++ return -EINVAL; ++ } ++} ++ ++int coda_mpeg4_level(int level_idc) ++{ ++ switch (level_idc) { ++ case 0: ++ return V4L2_MPEG_VIDEO_MPEG4_LEVEL_0; ++ case 1: ++ return V4L2_MPEG_VIDEO_MPEG4_LEVEL_1; ++ case 2: ++ return V4L2_MPEG_VIDEO_MPEG4_LEVEL_2; ++ case 3: ++ return V4L2_MPEG_VIDEO_MPEG4_LEVEL_3; ++ case 4: ++ return V4L2_MPEG_VIDEO_MPEG4_LEVEL_4; ++ case 5: ++ return V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; ++ default: ++ return -EINVAL; ++ } ++} ++ ++/* ++ * Check if the buffer starts with the MPEG-4 visual object sequence and visual ++ * object headers, for example: ++ * ++ * 00 00 01 b0 f1 ++ * 00 00 01 b5 a9 13 00 00 01 00 00 00 01 20 08 ++ * d4 8d 88 00 f5 04 04 08 14 30 3f ++ * ++ * Returns the detected header size in bytes or 0. ++ */ ++u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size) ++{ ++ static const u8 vos_start[4] = { 0x00, 0x00, 0x01, 0xb0 }; ++ static const union { ++ u8 vo_start[4]; ++ u8 start_code_prefix[3]; ++ } u = { { 0x00, 0x00, 0x01, 0xb5 } }; ++ ++ if (size < 30 || ++ memcmp(buf, vos_start, 4) != 0 || ++ memcmp(buf + 5, u.vo_start, 4) != 0) ++ return 0; ++ ++ if (size == 30 || ++ (size >= 33 && memcmp(buf + 30, u.start_code_prefix, 3) == 0)) ++ return 30; ++ ++ if (size == 31 || ++ (size >= 34 && memcmp(buf + 31, u.start_code_prefix, 3) == 0)) ++ return 31; ++ ++ if (size == 32 || ++ (size >= 35 && memcmp(buf + 32, u.start_code_prefix, 3) == 0)) ++ return 32; ++ ++ return 0; ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda_regs.h b/drivers/media/platform/chips-media/coda/coda_regs.h +--- a/drivers/media/platform/chips-media/coda/coda_regs.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/coda_regs.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,563 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * linux/drivers/media/platform/chips-media/coda_regs.h ++ * ++ * Copyright (C) 2012 Vista Silicon SL ++ * Javier Martin ++ * Xavier Duret ++ */ ++ ++#ifndef _REGS_CODA_H_ ++#define _REGS_CODA_H_ ++ ++/* HW registers */ ++#define CODA_REG_BIT_CODE_RUN 0x000 ++#define CODA_REG_RUN_ENABLE (1 << 0) ++#define CODA_REG_BIT_CODE_DOWN 0x004 ++#define CODA_DOWN_ADDRESS_SET(x) (((x) & 0xffff) << 16) ++#define CODA_DOWN_DATA_SET(x) ((x) & 0xffff) ++#define CODA_REG_BIT_HOST_IN_REQ 0x008 ++#define CODA_REG_BIT_INT_CLEAR 0x00c ++#define CODA_REG_BIT_INT_CLEAR_SET 0x1 ++#define CODA_REG_BIT_INT_STATUS 0x010 ++#define CODA_REG_BIT_CODE_RESET 0x014 ++#define CODA_REG_RESET_ENABLE (1 << 0) ++#define CODA_REG_BIT_CUR_PC 0x018 ++#define CODA9_REG_BIT_SW_RESET 0x024 ++#define CODA9_SW_RESET_BPU_CORE 0x008 ++#define CODA9_SW_RESET_BPU_BUS 0x010 ++#define CODA9_SW_RESET_VCE_CORE 0x020 ++#define CODA9_SW_RESET_VCE_BUS 0x040 ++#define CODA9_SW_RESET_GDI_CORE 0x080 ++#define CODA9_SW_RESET_GDI_BUS 0x100 ++#define CODA9_REG_BIT_SW_RESET_STATUS 0x034 ++ ++/* Static SW registers */ ++#define CODA_REG_BIT_CODE_BUF_ADDR 0x100 ++#define CODA_REG_BIT_WORK_BUF_ADDR 0x104 ++#define CODA_REG_BIT_PARA_BUF_ADDR 0x108 ++#define CODA_REG_BIT_STREAM_CTRL 0x10c ++#define CODA7_STREAM_BUF_PIC_RESET (1 << 4) ++#define CODADX6_STREAM_BUF_PIC_RESET (1 << 3) ++#define CODA7_STREAM_BUF_PIC_FLUSH (1 << 3) ++#define CODADX6_STREAM_BUF_PIC_FLUSH (1 << 2) ++#define CODA7_STREAM_BUF_DYNALLOC_EN (1 << 5) ++#define CODADX6_STREAM_BUF_DYNALLOC_EN (1 << 4) ++#define CODADX6_STREAM_CHKDIS_OFFSET (1 << 1) ++#define CODA7_STREAM_SEL_64BITS_ENDIAN (1 << 1) ++#define CODA_STREAM_ENDIAN_SELECT (1 << 0) ++#define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 ++#define CODA9_FRAME_ENABLE_BWB (1 << 12) ++#define CODA9_FRAME_TILED2LINEAR (1 << 11) ++#define CODA_FRAME_CHROMA_INTERLEAVE (1 << 2) ++#define CODA_IMAGE_ENDIAN_SELECT (1 << 0) ++#define CODA_REG_BIT_BIT_STREAM_PARAM 0x114 ++#define CODA_BIT_STREAM_END_FLAG (1 << 2) ++#define CODA_BIT_DEC_SEQ_INIT_ESCAPE (1 << 0) ++#define CODA_REG_BIT_TEMP_BUF_ADDR 0x118 ++#define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x)) ++#define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x)) ++#define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x)) ++#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 ++#define CODA7_REG_BIT_AXI_SRAM_USE 0x140 ++#define CODA9_USE_HOST_BTP_ENABLE (1 << 13) ++#define CODA9_USE_HOST_OVL_ENABLE (1 << 12) ++#define CODA7_USE_HOST_ME_ENABLE (1 << 11) ++#define CODA9_USE_HOST_DBK_ENABLE (3 << 10) ++#define CODA7_USE_HOST_OVL_ENABLE (1 << 10) ++#define CODA7_USE_HOST_DBK_ENABLE (1 << 9) ++#define CODA9_USE_HOST_IP_ENABLE (1 << 9) ++#define CODA7_USE_HOST_IP_ENABLE (1 << 8) ++#define CODA9_USE_HOST_BIT_ENABLE (1 << 8) ++#define CODA7_USE_HOST_BIT_ENABLE (1 << 7) ++#define CODA9_USE_BTP_ENABLE (1 << 5) ++#define CODA7_USE_ME_ENABLE (1 << 4) ++#define CODA9_USE_OVL_ENABLE (1 << 4) ++#define CODA7_USE_OVL_ENABLE (1 << 3) ++#define CODA9_USE_DBK_ENABLE (3 << 2) ++#define CODA7_USE_DBK_ENABLE (1 << 2) ++#define CODA7_USE_IP_ENABLE (1 << 1) ++#define CODA7_USE_BIT_ENABLE (1 << 0) ++ ++#define CODA_REG_BIT_BUSY 0x160 ++#define CODA_REG_BIT_BUSY_FLAG 1 ++#define CODA_REG_BIT_RUN_COMMAND 0x164 ++#define CODA_COMMAND_SEQ_INIT 1 ++#define CODA_COMMAND_SEQ_END 2 ++#define CODA_COMMAND_PIC_RUN 3 ++#define CODA_COMMAND_SET_FRAME_BUF 4 ++#define CODA_COMMAND_ENCODE_HEADER 5 ++#define CODA_COMMAND_ENC_PARA_SET 6 ++#define CODA_COMMAND_DEC_PARA_SET 7 ++#define CODA_COMMAND_DEC_BUF_FLUSH 8 ++#define CODA_COMMAND_RC_CHANGE_PARAMETER 9 ++#define CODA_COMMAND_FIRMWARE_GET 0xf ++#define CODA_REG_BIT_RUN_INDEX 0x168 ++#define CODA_INDEX_SET(x) ((x) & 0x3) ++#define CODA_REG_BIT_RUN_COD_STD 0x16c ++#define CODADX6_MODE_DECODE_MP4 0 ++#define CODADX6_MODE_ENCODE_MP4 1 ++#define CODADX6_MODE_DECODE_H264 2 ++#define CODADX6_MODE_ENCODE_H264 3 ++#define CODA7_MODE_DECODE_H264 0 ++#define CODA7_MODE_DECODE_VC1 1 ++#define CODA7_MODE_DECODE_MP2 2 ++#define CODA7_MODE_DECODE_MP4 3 ++#define CODA7_MODE_DECODE_DV3 3 ++#define CODA7_MODE_DECODE_RV 4 ++#define CODA7_MODE_DECODE_MJPG 5 ++#define CODA7_MODE_ENCODE_H264 8 ++#define CODA7_MODE_ENCODE_MP4 11 ++#define CODA7_MODE_ENCODE_MJPG 13 ++#define CODA9_MODE_DECODE_H264 0 ++#define CODA9_MODE_DECODE_VC1 1 ++#define CODA9_MODE_DECODE_MP2 2 ++#define CODA9_MODE_DECODE_MP4 3 ++#define CODA9_MODE_DECODE_DV3 3 ++#define CODA9_MODE_DECODE_RV 4 ++#define CODA9_MODE_DECODE_AVS 5 ++#define CODA9_MODE_DECODE_MJPG 6 ++#define CODA9_MODE_DECODE_VPX 7 ++#define CODA9_MODE_ENCODE_H264 8 ++#define CODA9_MODE_ENCODE_MP4 11 ++#define CODA9_MODE_ENCODE_MJPG 13 ++#define CODA_MODE_INVALID 0xffff ++#define CODA_REG_BIT_INT_ENABLE 0x170 ++#define CODA_INT_INTERRUPT_ENABLE (1 << 3) ++#define CODA_REG_BIT_INT_REASON 0x174 ++#define CODA7_REG_BIT_RUN_AUX_STD 0x178 ++#define CODA_MP4_AUX_MPEG4 0 ++#define CODA_MP4_AUX_DIVX3 1 ++#define CODA_VPX_AUX_THO 0 ++#define CODA_VPX_AUX_VP6 1 ++#define CODA_VPX_AUX_VP8 2 ++#define CODA_H264_AUX_AVC 0 ++#define CODA_H264_AUX_MVC 1 ++ ++/* ++ * Commands' mailbox: ++ * registers with offsets in the range 0x180-0x1d0 ++ * have different meaning depending on the command being ++ * issued. ++ */ ++ ++/* Decoder Sequence Initialization */ ++#define CODA_CMD_DEC_SEQ_BB_START 0x180 ++#define CODA_CMD_DEC_SEQ_BB_SIZE 0x184 ++#define CODA_CMD_DEC_SEQ_OPTION 0x188 ++#define CODA_NO_INT_ENABLE (1 << 10) ++#define CODA_REORDER_ENABLE (1 << 1) ++#define CODADX6_QP_REPORT (1 << 0) ++#define CODA7_MP4_DEBLK_ENABLE (1 << 0) ++#define CODA_CMD_DEC_SEQ_SRC_SIZE 0x18c ++#define CODA_CMD_DEC_SEQ_START_BYTE 0x190 ++#define CODA_CMD_DEC_SEQ_PS_BB_START 0x194 ++#define CODA_CMD_DEC_SEQ_PS_BB_SIZE 0x198 ++#define CODA_CMD_DEC_SEQ_JPG_THUMB_EN 0x19c ++#define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS 0x19c ++#define CODA_MP4_CLASS_MPEG4 0 ++#define CODA_CMD_DEC_SEQ_X264_MV_EN 0x19c ++#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0 ++ ++#define CODA7_RET_DEC_SEQ_ASPECT 0x1b0 ++#define CODA9_RET_DEC_SEQ_BITRATE 0x1b4 ++#define CODA_RET_DEC_SEQ_SUCCESS 0x1c0 ++#define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */ ++#define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4 ++#define CODA_RET_DEC_SEQ_SRC_F_RATE 0x1c8 ++#define CODA9_RET_DEC_SEQ_ASPECT 0x1c8 ++#define CODA_RET_DEC_SEQ_FRAME_NEED 0x1cc ++#define CODA_RET_DEC_SEQ_FRAME_DELAY 0x1d0 ++#define CODA_RET_DEC_SEQ_INFO 0x1d4 ++#define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT 0x1d8 ++#define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM 0x1dc ++#define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM 0x1e0 ++#define CODA_RET_DEC_SEQ_ERR_REASON 0x1e0 ++#define CODA_RET_DEC_SEQ_FRATE_NR 0x1e4 ++#define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8 ++#define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4 ++#define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8 ++#define CODA7_RET_DEC_SEQ_HEADER_REPORT 0x1ec ++ ++/* Decoder Picture Run */ ++#define CODA_CMD_DEC_PIC_ROT_MODE 0x180 ++#define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184 ++#define CODA9_CMD_DEC_PIC_ROT_INDEX 0x184 ++#define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188 ++#define CODA9_CMD_DEC_PIC_ROT_ADDR_Y 0x188 ++#define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c ++#define CODA9_CMD_DEC_PIC_ROT_ADDR_CB 0x18c ++#define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190 ++#define CODA9_CMD_DEC_PIC_ROT_ADDR_CR 0x190 ++#define CODA9_CMD_DEC_PIC_ROT_STRIDE 0x1b8 ++ ++#define CODA_CMD_DEC_PIC_OPTION 0x194 ++#define CODA_PRE_SCAN_EN (1 << 0) ++#define CODA_PRE_SCAN_MODE_DECODE (0 << 1) ++#define CODA_PRE_SCAN_MODE_RETURN (1 << 1) ++#define CODA_IFRAME_SEARCH_EN (1 << 2) ++#define CODA_SKIP_FRAME_MODE (0x3 << 3) ++#define CODA_CMD_DEC_PIC_SKIP_NUM 0x198 ++#define CODA_CMD_DEC_PIC_CHUNK_SIZE 0x19c ++#define CODA_CMD_DEC_PIC_BB_START 0x1a0 ++#define CODA_CMD_DEC_PIC_START_BYTE 0x1a4 ++#define CODA_RET_DEC_PIC_SIZE 0x1bc ++#define CODA_RET_DEC_PIC_FRAME_NUM 0x1c0 ++#define CODA_RET_DEC_PIC_FRAME_IDX 0x1c4 ++#define CODA_RET_DEC_PIC_ERR_MB 0x1c8 ++#define CODA_RET_DEC_PIC_TYPE 0x1cc ++#define CODA_PIC_TYPE_MASK 0x7 ++#define CODA_PIC_TYPE_MASK_VC1 0x3f ++#define CODA9_PIC_TYPE_FIRST_MASK (0x7 << 3) ++#define CODA9_PIC_TYPE_IDR_MASK (0x3 << 6) ++#define CODA7_PIC_TYPE_H264_NPF_MASK (0x3 << 16) ++#define CODA7_PIC_TYPE_INTERLACED (1 << 18) ++#define CODA_RET_DEC_PIC_POST 0x1d0 ++#define CODA_RET_DEC_PIC_MVC_REPORT 0x1d0 ++#define CODA_RET_DEC_PIC_OPTION 0x1d4 ++#define CODA_RET_DEC_PIC_SUCCESS 0x1d8 ++#define CODA_RET_DEC_PIC_CUR_IDX 0x1dc ++#define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT 0x1e0 ++#define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4 ++#define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec ++ ++#define CODA9_RET_DEC_PIC_VP8_PIC_REPORT 0x1e8 ++#define CODA9_RET_DEC_PIC_ASPECT 0x1f0 ++#define CODA9_RET_DEC_PIC_VP8_SCALE_INFO 0x1f0 ++#define CODA9_RET_DEC_PIC_FRATE_NR 0x1f4 ++#define CODA9_RET_DEC_PIC_FRATE_DR 0x1f8 ++ ++/* Encoder Sequence Initialization */ ++#define CODA_CMD_ENC_SEQ_BB_START 0x180 ++#define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 ++#define CODA_CMD_ENC_SEQ_OPTION 0x188 ++#define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9 ++#define CODA9_OPTION_MVC_PREFIX_NAL_OFFSET 9 ++#define CODA7_OPTION_GAMMA_OFFSET 8 ++#define CODA9_OPTION_MVC_PARASET_REFRESH_OFFSET 8 ++#define CODA7_OPTION_RCQPMAX_OFFSET 7 ++#define CODA9_OPTION_GAMMA_OFFSET 7 ++#define CODADX6_OPTION_GAMMA_OFFSET 7 ++#define CODA7_OPTION_RCQPMIN_OFFSET 6 ++#define CODA9_OPTION_RCQPMAX_OFFSET 6 ++#define CODA_OPTION_LIMITQP_OFFSET 6 ++#define CODA_OPTION_RCINTRAQP_OFFSET 5 ++#define CODA_OPTION_FMO_OFFSET 4 ++#define CODA9_OPTION_MVC_INTERVIEW_OFFSET 4 ++#define CODA_OPTION_AVC_AUD_OFFSET 2 ++#define CODA_OPTION_SLICEREPORT_OFFSET 1 ++#define CODA_CMD_ENC_SEQ_COD_STD 0x18c ++#define CODA_STD_MPEG4 0 ++#define CODA9_STD_H264 0 ++#define CODA_STD_H263 1 ++#define CODA_STD_H264 2 ++#define CODA9_STD_MPEG4 3 ++ ++#define CODA_CMD_ENC_SEQ_SRC_SIZE 0x190 ++#define CODA7_PICWIDTH_OFFSET 16 ++#define CODA7_PICWIDTH_MASK 0xffff ++#define CODADX6_PICWIDTH_OFFSET 10 ++#define CODADX6_PICWIDTH_MASK 0x3ff ++#define CODA_PICHEIGHT_OFFSET 0 ++#define CODADX6_PICHEIGHT_MASK 0x3ff ++#define CODA7_PICHEIGHT_MASK 0xffff ++#define CODA_CMD_ENC_SEQ_SRC_F_RATE 0x194 ++#define CODA_FRATE_RES_OFFSET 0 ++#define CODA_FRATE_RES_MASK 0xffff ++#define CODA_FRATE_DIV_OFFSET 16 ++#define CODA_FRATE_DIV_MASK 0xffff ++#define CODA_CMD_ENC_SEQ_MP4_PARA 0x198 ++#define CODA_MP4PARAM_VERID_OFFSET 6 ++#define CODA_MP4PARAM_VERID_MASK 0x01 ++#define CODA_MP4PARAM_INTRADCVLCTHR_OFFSET 2 ++#define CODA_MP4PARAM_INTRADCVLCTHR_MASK 0x07 ++#define CODA_MP4PARAM_REVERSIBLEVLCENABLE_OFFSET 1 ++#define CODA_MP4PARAM_REVERSIBLEVLCENABLE_MASK 0x01 ++#define CODA_MP4PARAM_DATAPARTITIONENABLE_OFFSET 0 ++#define CODA_MP4PARAM_DATAPARTITIONENABLE_MASK 0x01 ++#define CODA_CMD_ENC_SEQ_263_PARA 0x19c ++#define CODA_263PARAM_ANNEXJENABLE_OFFSET 2 ++#define CODA_263PARAM_ANNEXJENABLE_MASK 0x01 ++#define CODA_263PARAM_ANNEXKENABLE_OFFSET 1 ++#define CODA_263PARAM_ANNEXKENABLE_MASK 0x01 ++#define CODA_263PARAM_ANNEXTENABLE_OFFSET 0 ++#define CODA_263PARAM_ANNEXTENABLE_MASK 0x01 ++#define CODA_CMD_ENC_SEQ_264_PARA 0x1a0 ++#define CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET 12 ++#define CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK 0x0f ++#define CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET 8 ++#define CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK 0x0f ++#define CODA_264PARAM_DISABLEDEBLK_OFFSET 6 ++#define CODA_264PARAM_DISABLEDEBLK_MASK 0x03 ++#define CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET 5 ++#define CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_MASK 0x01 ++#define CODA_264PARAM_CHROMAQPOFFSET_OFFSET 0 ++#define CODA_264PARAM_CHROMAQPOFFSET_MASK 0x1f ++#define CODA_CMD_ENC_SEQ_SLICE_MODE 0x1a4 ++#define CODA_SLICING_SIZE_OFFSET 2 ++#define CODA_SLICING_SIZE_MASK 0x3fffffff ++#define CODA_SLICING_UNIT_OFFSET 1 ++#define CODA_SLICING_UNIT_MASK 0x01 ++#define CODA_SLICING_MODE_OFFSET 0 ++#define CODA_SLICING_MODE_MASK 0x01 ++#define CODA_CMD_ENC_SEQ_GOP_SIZE 0x1a8 ++#define CODA_GOP_SIZE_OFFSET 0 ++#define CODA_GOP_SIZE_MASK 0x3f ++#define CODA_CMD_ENC_SEQ_RC_PARA 0x1ac ++#define CODA_RATECONTROL_AUTOSKIP_OFFSET 31 ++#define CODA_RATECONTROL_AUTOSKIP_MASK 0x01 ++#define CODA_RATECONTROL_INITIALDELAY_OFFSET 16 ++#define CODA_RATECONTROL_INITIALDELAY_MASK 0x7fff ++#define CODA_RATECONTROL_BITRATE_OFFSET 1 ++#define CODA_RATECONTROL_BITRATE_MASK 0x7fff ++#define CODA_RATECONTROL_ENABLE_OFFSET 0 ++#define CODA_RATECONTROL_ENABLE_MASK 0x01 ++#define CODA_CMD_ENC_SEQ_RC_BUF_SIZE 0x1b0 ++#define CODA_CMD_ENC_SEQ_INTRA_REFRESH 0x1b4 ++#define CODADX6_CMD_ENC_SEQ_FMO 0x1b8 ++#define CODA_FMOPARAM_TYPE_OFFSET 4 ++#define CODA_FMOPARAM_TYPE_MASK 1 ++#define CODA_FMOPARAM_SLICENUM_OFFSET 0 ++#define CODA_FMOPARAM_SLICENUM_MASK 0x0f ++#define CODADX6_CMD_ENC_SEQ_INTRA_QP 0x1bc ++#define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 ++#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc ++#define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4 ++#define CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX 0x1c8 ++#define CODA_QPMIN_OFFSET 8 ++#define CODA_QPMIN_MASK 0x3f ++#define CODA_QPMAX_OFFSET 0 ++#define CODA_QPMAX_MASK 0x3f ++#define CODA_CMD_ENC_SEQ_RC_GAMMA 0x1cc ++#define CODA_GAMMA_OFFSET 0 ++#define CODA_GAMMA_MASK 0xffff ++#define CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE 0x1d0 ++#define CODA9_CMD_ENC_SEQ_INTRA_WEIGHT 0x1d4 ++#define CODA9_CMD_ENC_SEQ_ME_OPTION 0x1d8 ++#define CODA_RET_ENC_SEQ_SUCCESS 0x1c0 ++ ++#define CODA_CMD_ENC_SEQ_JPG_PARA 0x198 ++#define CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL 0x19C ++#define CODA_CMD_ENC_SEQ_JPG_THUMB_EN 0x1a0 ++#define CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE 0x1a4 ++#define CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET 0x1a8 ++ ++/* Encoder Parameter Change */ ++#define CODA_CMD_ENC_PARAM_CHANGE_ENABLE 0x180 ++#define CODA_PARAM_CHANGE_RC_GOP BIT(0) ++#define CODA_PARAM_CHANGE_RC_INTRA_QP BIT(1) ++#define CODA_PARAM_CHANGE_RC_BITRATE BIT(2) ++#define CODA_PARAM_CHANGE_RC_FRAME_RATE BIT(3) ++#define CODA_PARAM_CHANGE_INTRA_MB_NUM BIT(4) ++#define CODA_PARAM_CHANGE_SLICE_MODE BIT(5) ++#define CODA_PARAM_CHANGE_HEC_MODE BIT(6) ++#define CODA_CMD_ENC_PARAM_RC_GOP 0x184 ++#define CODA_CMD_ENC_PARAM_RC_INTRA_QP 0x188 ++#define CODA_CMD_ENC_PARAM_RC_BITRATE 0x18c ++#define CODA_CMD_ENC_PARAM_RC_FRAME_RATE 0x190 ++#define CODA_CMD_ENC_PARAM_INTRA_MB_NUM 0x194 ++#define CODA_CMD_ENC_PARAM_SLICE_MODE 0x198 ++#define CODA_CMD_ENC_PARAM_HEC_MODE 0x19c ++#define CODA_RET_ENC_PARAM_CHANGE_SUCCESS 0x1c0 ++ ++/* Encoder Picture Run */ ++#define CODA9_CMD_ENC_PIC_SRC_INDEX 0x180 ++#define CODA9_CMD_ENC_PIC_SRC_STRIDE 0x184 ++#define CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC 0x1a4 ++#define CODA9_CMD_ENC_PIC_SRC_ADDR_Y 0x1a8 ++#define CODA9_CMD_ENC_PIC_SRC_ADDR_CB 0x1ac ++#define CODA9_CMD_ENC_PIC_SRC_ADDR_CR 0x1b0 ++#define CODA_CMD_ENC_PIC_SRC_ADDR_Y 0x180 ++#define CODA_CMD_ENC_PIC_SRC_ADDR_CB 0x184 ++#define CODA_CMD_ENC_PIC_SRC_ADDR_CR 0x188 ++#define CODA_CMD_ENC_PIC_QS 0x18c ++#define CODA_CMD_ENC_PIC_ROT_MODE 0x190 ++#define CODA_ROT_MIR_ENABLE (1 << 4) ++#define CODA_ROT_0 (0x0 << 0) ++#define CODA_ROT_90 (0x1 << 0) ++#define CODA_ROT_180 (0x2 << 0) ++#define CODA_ROT_270 (0x3 << 0) ++#define CODA_MIR_NONE (0x0 << 2) ++#define CODA_MIR_VER (0x1 << 2) ++#define CODA_MIR_HOR (0x2 << 2) ++#define CODA_MIR_VER_HOR (0x3 << 2) ++#define CODA_CMD_ENC_PIC_OPTION 0x194 ++#define CODA_FORCE_IPICTURE BIT(1) ++#define CODA_REPORT_MB_INFO BIT(3) ++#define CODA_REPORT_MV_INFO BIT(4) ++#define CODA_REPORT_SLICE_INFO BIT(5) ++#define CODA_CMD_ENC_PIC_BB_START 0x198 ++#define CODA_CMD_ENC_PIC_BB_SIZE 0x19c ++#define CODA_RET_ENC_FRAME_NUM 0x1c0 ++#define CODA_RET_ENC_PIC_TYPE 0x1c4 ++#define CODA_RET_ENC_PIC_FRAME_IDX 0x1c8 ++#define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc ++#define CODA_RET_ENC_PIC_FLAG 0x1d0 ++#define CODA_RET_ENC_PIC_SUCCESS 0x1d8 ++ ++/* Set Frame Buffer */ ++#define CODA_CMD_SET_FRAME_BUF_NUM 0x180 ++#define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 ++#define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188 ++#define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c ++#define CODA9_CMD_SET_FRAME_SUBSAMP_A 0x188 ++#define CODA9_CMD_SET_FRAME_SUBSAMP_B 0x18c ++#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 ++#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 ++#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 ++#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c ++#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 ++#define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4 ++#define CODA9_CMD_SET_FRAME_AXI_BTP_ADDR 0x1a4 ++#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 ++#define CODA9_CMD_SET_FRAME_CACHE_SIZE 0x1a8 ++#define CODA9_CMD_SET_FRAME_CACHE_CONFIG 0x1ac ++#define CODA9_CACHE_BYPASS_OFFSET 28 ++#define CODA9_CACHE_DUALCONF_OFFSET 26 ++#define CODA9_CACHE_PAGEMERGE_OFFSET 24 ++#define CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET 16 ++#define CODA9_CACHE_CB_BUFFER_SIZE_OFFSET 8 ++#define CODA9_CACHE_CR_BUFFER_SIZE_OFFSET 0 ++#define CODA9_CMD_SET_FRAME_SUBSAMP_A_MVC 0x1b0 ++#define CODA9_CMD_SET_FRAME_SUBSAMP_B_MVC 0x1b4 ++#define CODA9_CMD_SET_FRAME_DP_BUF_BASE 0x1b0 ++#define CODA9_CMD_SET_FRAME_DP_BUF_SIZE 0x1b4 ++#define CODA9_CMD_SET_FRAME_MAX_DEC_SIZE 0x1b8 ++#define CODA9_CMD_SET_FRAME_DELAY 0x1bc ++ ++/* Encoder Header */ ++#define CODA_CMD_ENC_HEADER_CODE 0x180 ++#define CODA_GAMMA_OFFSET 0 ++#define CODA_HEADER_H264_SPS 0 ++#define CODA_HEADER_H264_PPS 1 ++#define CODA_HEADER_MP4V_VOL 0 ++#define CODA_HEADER_MP4V_VOS 1 ++#define CODA_HEADER_MP4V_VIS 2 ++#define CODA9_HEADER_FRAME_CROP (1 << 3) ++#define CODA_CMD_ENC_HEADER_BB_START 0x184 ++#define CODA_CMD_ENC_HEADER_BB_SIZE 0x188 ++#define CODA9_CMD_ENC_HEADER_FRAME_CROP_H 0x18c ++#define CODA9_CMD_ENC_HEADER_FRAME_CROP_V 0x190 ++ ++/* Get Version */ ++#define CODA_CMD_FIRMWARE_VERNUM 0x1c0 ++#define CODA_FIRMWARE_PRODUCT(x) (((x) >> 16) & 0xffff) ++#define CODA_FIRMWARE_MAJOR(x) (((x) >> 12) & 0x0f) ++#define CODA_FIRMWARE_MINOR(x) (((x) >> 8) & 0x0f) ++#define CODA_FIRMWARE_RELEASE(x) ((x) & 0xff) ++#define CODA_FIRMWARE_VERNUM(product, major, minor, release) \ ++ ((product) << 16 | ((major) << 12) | \ ++ ((minor) << 8) | (release)) ++#define CODA9_CMD_FIRMWARE_CODE_REV 0x1c4 ++ ++#define CODA9_GDMA_BASE 0x1000 ++#define CODA9_GDI_CONTROL (CODA9_GDMA_BASE + 0x034) ++#define CODA9_GDI_PIC_INIT_HOST (CODA9_GDMA_BASE + 0x038) ++#define CODA9_GDI_STATUS (CODA9_GDMA_BASE + 0x080) ++#define CODA9_GDI_WPROT_ERR_CLR (CODA9_GDMA_BASE + 0x0a0) ++#define CODA9_GDI_WPROT_RGN_EN (CODA9_GDMA_BASE + 0x0ac) ++ ++#define CODA9_GDI_BUS_CTRL (CODA9_GDMA_BASE + 0x0f0) ++#define CODA9_GDI_BUS_STATUS (CODA9_GDMA_BASE + 0x0f4) ++ ++#define CODA9_GDI_INFO_CONTROL (CODA9_GDMA_BASE + 0x400) ++#define CODA9_GDI_INFO_PIC_SIZE (CODA9_GDMA_BASE + 0x404) ++#define CODA9_GDI_INFO_BASE_Y (CODA9_GDMA_BASE + 0x408) ++#define CODA9_GDI_INFO_BASE_CB (CODA9_GDMA_BASE + 0x40c) ++#define CODA9_GDI_INFO_BASE_CR (CODA9_GDMA_BASE + 0x410) ++ ++#define CODA9_GDI_XY2_CAS_0 (CODA9_GDMA_BASE + 0x800) ++#define CODA9_GDI_XY2_CAS_F (CODA9_GDMA_BASE + 0x83c) ++ ++#define CODA9_GDI_XY2_BA_0 (CODA9_GDMA_BASE + 0x840) ++#define CODA9_GDI_XY2_BA_1 (CODA9_GDMA_BASE + 0x844) ++#define CODA9_GDI_XY2_BA_2 (CODA9_GDMA_BASE + 0x848) ++#define CODA9_GDI_XY2_BA_3 (CODA9_GDMA_BASE + 0x84c) ++ ++#define CODA9_GDI_XY2_RAS_0 (CODA9_GDMA_BASE + 0x850) ++#define CODA9_GDI_XY2_RAS_F (CODA9_GDMA_BASE + 0x88c) ++ ++#define CODA9_GDI_XY2_RBC_CONFIG (CODA9_GDMA_BASE + 0x890) ++#define CODA9_XY2RBC_SEPARATE_MAP BIT(19) ++#define CODA9_XY2RBC_TOP_BOT_SPLIT BIT(18) ++#define CODA9_XY2RBC_TILED_MAP BIT(17) ++#define CODA9_XY2RBC_CA_INC_HOR BIT(16) ++#define CODA9_GDI_RBC2_AXI_0 (CODA9_GDMA_BASE + 0x8a0) ++#define CODA9_GDI_RBC2_AXI_1F (CODA9_GDMA_BASE + 0x91c) ++#define CODA9_GDI_TILEDBUF_BASE (CODA9_GDMA_BASE + 0x920) ++ ++#define CODA9_JPEG_BASE 0x3000 ++#define CODA9_REG_JPEG_PIC_START (CODA9_JPEG_BASE + 0x000) ++#define CODA9_REG_JPEG_PIC_STATUS (CODA9_JPEG_BASE + 0x004) ++#define CODA9_JPEG_STATUS_OVERFLOW BIT(3) ++#define CODA9_JPEG_STATUS_BBC_INT BIT(2) ++#define CODA9_JPEG_STATUS_ERROR BIT(1) ++#define CODA9_JPEG_STATUS_DONE BIT(0) ++#define CODA9_REG_JPEG_PIC_ERRMB (CODA9_JPEG_BASE + 0x008) ++#define CODA9_JPEG_ERRMB_RESTART_IDX_MASK (0xf << 24) ++#define CODA9_JPEG_ERRMB_MCU_POS_X_MASK (0xfff << 12) ++#define CODA9_JPEG_ERRMB_MCU_POS_Y_MASK 0xfff ++#define CODA9_REG_JPEG_PIC_CTRL (CODA9_JPEG_BASE + 0x010) ++#define CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN BIT(6) ++#define CODA9_JPEG_PIC_CTRL_TC_DIRECTION BIT(4) ++#define CODA9_JPEG_PIC_CTRL_ENCODER_EN BIT(3) ++#define CODA9_REG_JPEG_PIC_SIZE (CODA9_JPEG_BASE + 0x014) ++#define CODA9_REG_JPEG_MCU_INFO (CODA9_JPEG_BASE + 0x018) ++#define CODA9_JPEG_MCU_BLOCK_NUM_OFFSET 16 ++#define CODA9_JPEG_COMP_NUM_OFFSET 12 ++#define CODA9_JPEG_COMP0_INFO_OFFSET 8 ++#define CODA9_JPEG_COMP1_INFO_OFFSET 4 ++#define CODA9_JPEG_COMP2_INFO_OFFSET 0 ++#define CODA9_REG_JPEG_ROT_INFO (CODA9_JPEG_BASE + 0x01c) ++#define CODA9_JPEG_ROT_MIR_ENABLE BIT(4) ++#define CODA9_JPEG_ROT_MIR_MODE_MASK 0xf ++#define CODA9_REG_JPEG_SCL_INFO (CODA9_JPEG_BASE + 0x020) ++#define CODA9_JPEG_SCL_ENABLE BIT(4) ++#define CODA9_JPEG_SCL_HOR_MODE_MASK (0x3 << 2) ++#define CODA9_JPEG_SCL_VER_MODE_MASK (0x3 << 0) ++#define CODA9_REG_JPEG_IF_INFO (CODA9_JPEG_BASE + 0x024) ++#define CODA9_JPEG_SENS_IF_CLR BIT(1) ++#define CODA9_JPEG_DISP_IF_CLR BIT(0) ++#define CODA9_REG_JPEG_OP_INFO (CODA9_JPEG_BASE + 0x02c) ++#define CODA9_JPEG_BUS_REQ_NUM_OFFSET 0 ++#define CODA9_JPEG_BUS_REQ_NUM_MASK 0x7 ++#define CODA9_REG_JPEG_DPB_CONFIG (CODA9_JPEG_BASE + 0x030) ++#define CODA9_REG_JPEG_DPB_BASE00 (CODA9_JPEG_BASE + 0x040) ++#define CODA9_REG_JPEG_HUFF_CTRL (CODA9_JPEG_BASE + 0x080) ++#define CODA9_REG_JPEG_HUFF_ADDR (CODA9_JPEG_BASE + 0x084) ++#define CODA9_REG_JPEG_HUFF_DATA (CODA9_JPEG_BASE + 0x088) ++#define CODA9_REG_JPEG_QMAT_CTRL (CODA9_JPEG_BASE + 0x090) ++#define CODA9_REG_JPEG_QMAT_ADDR (CODA9_JPEG_BASE + 0x094) ++#define CODA9_REG_JPEG_QMAT_DATA (CODA9_JPEG_BASE + 0x098) ++#define CODA9_REG_JPEG_RST_INTVAL (CODA9_JPEG_BASE + 0x0b0) ++#define CODA9_REG_JPEG_RST_INDEX (CODA9_JPEG_BASE + 0x0b4) ++#define CODA9_REG_JPEG_RST_COUNT (CODA9_JPEG_BASE + 0x0b8) ++#define CODA9_REG_JPEG_DPCM_DIFF_Y (CODA9_JPEG_BASE + 0x0f0) ++#define CODA9_REG_JPEG_DPCM_DIFF_CB (CODA9_JPEG_BASE + 0x0f4) ++#define CODA9_REG_JPEG_DPCM_DIFF_CR (CODA9_JPEG_BASE + 0x0f8) ++#define CODA9_REG_JPEG_GBU_CTRL (CODA9_JPEG_BASE + 0x100) ++#define CODA9_REG_JPEG_GBU_BT_PTR (CODA9_JPEG_BASE + 0x110) ++#define CODA9_REG_JPEG_GBU_WD_PTR (CODA9_JPEG_BASE + 0x114) ++#define CODA9_REG_JPEG_GBU_TT_CNT (CODA9_JPEG_BASE + 0x118) ++#define CODA9_REG_JPEG_GBU_BBSR (CODA9_JPEG_BASE + 0x140) ++#define CODA9_REG_JPEG_GBU_BBER (CODA9_JPEG_BASE + 0x144) ++#define CODA9_REG_JPEG_GBU_BBIR (CODA9_JPEG_BASE + 0x148) ++#define CODA9_REG_JPEG_GBU_BBHR (CODA9_JPEG_BASE + 0x14c) ++#define CODA9_REG_JPEG_GBU_BCNT (CODA9_JPEG_BASE + 0x158) ++#define CODA9_REG_JPEG_GBU_FF_RPTR (CODA9_JPEG_BASE + 0x160) ++#define CODA9_REG_JPEG_GBU_FF_WPTR (CODA9_JPEG_BASE + 0x164) ++#define CODA9_REG_JPEG_BBC_END_ADDR (CODA9_JPEG_BASE + 0x208) ++#define CODA9_REG_JPEG_BBC_WR_PTR (CODA9_JPEG_BASE + 0x20c) ++#define CODA9_REG_JPEG_BBC_RD_PTR (CODA9_JPEG_BASE + 0x210) ++#define CODA9_REG_JPEG_BBC_EXT_ADDR (CODA9_JPEG_BASE + 0x214) ++#define CODA9_REG_JPEG_BBC_INT_ADDR (CODA9_JPEG_BASE + 0x218) ++#define CODA9_REG_JPEG_BBC_DATA_CNT (CODA9_JPEG_BASE + 0x21c) ++#define CODA9_REG_JPEG_BBC_COMMAND (CODA9_JPEG_BASE + 0x220) ++#define CODA9_REG_JPEG_BBC_BUSY (CODA9_JPEG_BASE + 0x224) ++#define CODA9_REG_JPEG_BBC_CTRL (CODA9_JPEG_BASE + 0x228) ++#define CODA9_REG_JPEG_BBC_CUR_POS (CODA9_JPEG_BASE + 0x22c) ++#define CODA9_REG_JPEG_BBC_BAS_ADDR (CODA9_JPEG_BASE + 0x230) ++#define CODA9_REG_JPEG_BBC_STRM_CTRL (CODA9_JPEG_BASE + 0x234) ++#define CODA9_REG_JPEG_BBC_FLUSH_CMD (CODA9_JPEG_BASE + 0x238) ++ ++#endif +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/imx-vdoa.c b/drivers/media/platform/chips-media/coda/imx-vdoa.c +--- a/drivers/media/platform/chips-media/coda/imx-vdoa.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/imx-vdoa.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,346 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * i.MX6 Video Data Order Adapter (VDOA) ++ * ++ * Copyright (C) 2014 Philipp Zabel ++ * Copyright (C) 2016 Pengutronix, Michael Tretter ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "imx-vdoa.h" ++ ++#define VDOA_NAME "imx-vdoa" ++ ++#define VDOAC 0x00 ++#define VDOASRR 0x04 ++#define VDOAIE 0x08 ++#define VDOAIST 0x0c ++#define VDOAFP 0x10 ++#define VDOAIEBA00 0x14 ++#define VDOAIEBA01 0x18 ++#define VDOAIEBA02 0x1c ++#define VDOAIEBA10 0x20 ++#define VDOAIEBA11 0x24 ++#define VDOAIEBA12 0x28 ++#define VDOASL 0x2c ++#define VDOAIUBO 0x30 ++#define VDOAVEBA0 0x34 ++#define VDOAVEBA1 0x38 ++#define VDOAVEBA2 0x3c ++#define VDOAVUBO 0x40 ++#define VDOASR 0x44 ++ ++#define VDOAC_ISEL BIT(6) ++#define VDOAC_PFS BIT(5) ++#define VDOAC_SO BIT(4) ++#define VDOAC_SYNC BIT(3) ++#define VDOAC_NF BIT(2) ++#define VDOAC_BNDM_MASK 0x3 ++#define VDOAC_BAND_HEIGHT_8 0x0 ++#define VDOAC_BAND_HEIGHT_16 0x1 ++#define VDOAC_BAND_HEIGHT_32 0x2 ++ ++#define VDOASRR_START BIT(1) ++#define VDOASRR_SWRST BIT(0) ++ ++#define VDOAIE_EITERR BIT(1) ++#define VDOAIE_EIEOT BIT(0) ++ ++#define VDOAIST_TERR BIT(1) ++#define VDOAIST_EOT BIT(0) ++ ++#define VDOAFP_FH_MASK (0x1fff << 16) ++#define VDOAFP_FW_MASK (0x3fff) ++ ++#define VDOASL_VSLY_MASK (0x3fff << 16) ++#define VDOASL_ISLY_MASK (0x7fff) ++ ++#define VDOASR_ERRW BIT(4) ++#define VDOASR_EOB BIT(3) ++#define VDOASR_CURRENT_FRAME (0x3 << 1) ++#define VDOASR_CURRENT_BUFFER BIT(1) ++ ++enum { ++ V4L2_M2M_SRC = 0, ++ V4L2_M2M_DST = 1, ++}; ++ ++struct vdoa_data { ++ struct vdoa_ctx *curr_ctx; ++ struct device *dev; ++ struct clk *vdoa_clk; ++ void __iomem *regs; ++}; ++ ++struct vdoa_q_data { ++ unsigned int width; ++ unsigned int height; ++ unsigned int bytesperline; ++ unsigned int sizeimage; ++ u32 pixelformat; ++}; ++ ++struct vdoa_ctx { ++ struct vdoa_data *vdoa; ++ struct completion completion; ++ struct vdoa_q_data q_data[2]; ++ unsigned int submitted_job; ++ unsigned int completed_job; ++}; ++ ++static irqreturn_t vdoa_irq_handler(int irq, void *data) ++{ ++ struct vdoa_data *vdoa = data; ++ struct vdoa_ctx *curr_ctx; ++ u32 val; ++ ++ /* Disable interrupts */ ++ writel(0, vdoa->regs + VDOAIE); ++ ++ curr_ctx = vdoa->curr_ctx; ++ if (!curr_ctx) { ++ dev_warn(vdoa->dev, ++ "Instance released before the end of transaction\n"); ++ return IRQ_HANDLED; ++ } ++ ++ val = readl(vdoa->regs + VDOAIST); ++ writel(val, vdoa->regs + VDOAIST); ++ if (val & VDOAIST_TERR) { ++ val = readl(vdoa->regs + VDOASR) & VDOASR_ERRW; ++ dev_err(vdoa->dev, "AXI %s error\n", val ? "write" : "read"); ++ } else if (!(val & VDOAIST_EOT)) { ++ dev_warn(vdoa->dev, "Spurious interrupt\n"); ++ } ++ curr_ctx->completed_job++; ++ complete(&curr_ctx->completion); ++ ++ return IRQ_HANDLED; ++} ++ ++int vdoa_wait_for_completion(struct vdoa_ctx *ctx) ++{ ++ struct vdoa_data *vdoa = ctx->vdoa; ++ ++ if (ctx->submitted_job == ctx->completed_job) ++ return 0; ++ ++ if (!wait_for_completion_timeout(&ctx->completion, ++ msecs_to_jiffies(300))) { ++ dev_err(vdoa->dev, ++ "Timeout waiting for transfer result\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(vdoa_wait_for_completion); ++ ++void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src) ++{ ++ struct vdoa_q_data *src_q_data, *dst_q_data; ++ struct vdoa_data *vdoa = ctx->vdoa; ++ u32 val; ++ ++ if (vdoa->curr_ctx) ++ vdoa_wait_for_completion(vdoa->curr_ctx); ++ ++ vdoa->curr_ctx = ctx; ++ ++ reinit_completion(&ctx->completion); ++ ctx->submitted_job++; ++ ++ src_q_data = &ctx->q_data[V4L2_M2M_SRC]; ++ dst_q_data = &ctx->q_data[V4L2_M2M_DST]; ++ ++ /* Progressive, no sync, 1 frame per run */ ++ if (dst_q_data->pixelformat == V4L2_PIX_FMT_YUYV) ++ val = VDOAC_PFS; ++ else ++ val = 0; ++ writel(val, vdoa->regs + VDOAC); ++ ++ writel(dst_q_data->height << 16 | dst_q_data->width, ++ vdoa->regs + VDOAFP); ++ ++ val = dst; ++ writel(val, vdoa->regs + VDOAIEBA00); ++ ++ writel(src_q_data->bytesperline << 16 | dst_q_data->bytesperline, ++ vdoa->regs + VDOASL); ++ ++ if (dst_q_data->pixelformat == V4L2_PIX_FMT_NV12 || ++ dst_q_data->pixelformat == V4L2_PIX_FMT_NV21) ++ val = dst_q_data->bytesperline * dst_q_data->height; ++ else ++ val = 0; ++ writel(val, vdoa->regs + VDOAIUBO); ++ ++ val = src; ++ writel(val, vdoa->regs + VDOAVEBA0); ++ val = round_up(src_q_data->bytesperline * src_q_data->height, 4096); ++ writel(val, vdoa->regs + VDOAVUBO); ++ ++ /* Enable interrupts and start transfer */ ++ writel(VDOAIE_EITERR | VDOAIE_EIEOT, vdoa->regs + VDOAIE); ++ writel(VDOASRR_START, vdoa->regs + VDOASRR); ++} ++EXPORT_SYMBOL(vdoa_device_run); ++ ++struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa) ++{ ++ struct vdoa_ctx *ctx; ++ int err; ++ ++ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return NULL; ++ ++ err = clk_prepare_enable(vdoa->vdoa_clk); ++ if (err) { ++ kfree(ctx); ++ return NULL; ++ } ++ ++ init_completion(&ctx->completion); ++ ctx->vdoa = vdoa; ++ ++ return ctx; ++} ++EXPORT_SYMBOL(vdoa_context_create); ++ ++void vdoa_context_destroy(struct vdoa_ctx *ctx) ++{ ++ struct vdoa_data *vdoa = ctx->vdoa; ++ ++ if (vdoa->curr_ctx == ctx) { ++ vdoa_wait_for_completion(vdoa->curr_ctx); ++ vdoa->curr_ctx = NULL; ++ } ++ ++ clk_disable_unprepare(vdoa->vdoa_clk); ++ kfree(ctx); ++} ++EXPORT_SYMBOL(vdoa_context_destroy); ++ ++int vdoa_context_configure(struct vdoa_ctx *ctx, ++ unsigned int width, unsigned int height, ++ u32 pixelformat) ++{ ++ struct vdoa_q_data *src_q_data; ++ struct vdoa_q_data *dst_q_data; ++ ++ if (width < 16 || width > 8192 || width % 16 != 0 || ++ height < 16 || height > 4096 || height % 16 != 0) ++ return -EINVAL; ++ ++ if (pixelformat != V4L2_PIX_FMT_YUYV && ++ pixelformat != V4L2_PIX_FMT_NV12) ++ return -EINVAL; ++ ++ /* If no context is passed, only check if the format is valid */ ++ if (!ctx) ++ return 0; ++ ++ src_q_data = &ctx->q_data[V4L2_M2M_SRC]; ++ dst_q_data = &ctx->q_data[V4L2_M2M_DST]; ++ ++ src_q_data->width = width; ++ src_q_data->height = height; ++ src_q_data->bytesperline = width; ++ src_q_data->sizeimage = ++ round_up(src_q_data->bytesperline * height, 4096) + ++ src_q_data->bytesperline * height / 2; ++ ++ dst_q_data->width = width; ++ dst_q_data->height = height; ++ dst_q_data->pixelformat = pixelformat; ++ switch (pixelformat) { ++ case V4L2_PIX_FMT_YUYV: ++ dst_q_data->bytesperline = width * 2; ++ dst_q_data->sizeimage = dst_q_data->bytesperline * height; ++ break; ++ case V4L2_PIX_FMT_NV12: ++ default: ++ dst_q_data->bytesperline = width; ++ dst_q_data->sizeimage = ++ dst_q_data->bytesperline * height * 3 / 2; ++ break; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(vdoa_context_configure); ++ ++static int vdoa_probe(struct platform_device *pdev) ++{ ++ struct vdoa_data *vdoa; ++ int ret; ++ ++ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ if (ret) { ++ dev_err(&pdev->dev, "DMA enable failed\n"); ++ return ret; ++ } ++ ++ vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL); ++ if (!vdoa) ++ return -ENOMEM; ++ ++ vdoa->dev = &pdev->dev; ++ ++ vdoa->vdoa_clk = devm_clk_get(vdoa->dev, NULL); ++ if (IS_ERR(vdoa->vdoa_clk)) { ++ dev_err(vdoa->dev, "Failed to get clock\n"); ++ return PTR_ERR(vdoa->vdoa_clk); ++ } ++ ++ vdoa->regs = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(vdoa->regs)) ++ return PTR_ERR(vdoa->regs); ++ ++ ret = platform_get_irq(pdev, 0); ++ if (ret < 0) ++ return ret; ++ ret = devm_request_threaded_irq(&pdev->dev, ret, NULL, ++ vdoa_irq_handler, IRQF_ONESHOT, ++ "vdoa", vdoa); ++ if (ret < 0) { ++ dev_err(vdoa->dev, "Failed to get irq\n"); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, vdoa); ++ ++ return 0; ++} ++ ++static const struct of_device_id vdoa_dt_ids[] = { ++ { .compatible = "fsl,imx6q-vdoa" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, vdoa_dt_ids); ++ ++static struct platform_driver vdoa_driver = { ++ .probe = vdoa_probe, ++ .driver = { ++ .name = VDOA_NAME, ++ .of_match_table = vdoa_dt_ids, ++ }, ++}; ++ ++module_platform_driver(vdoa_driver); ++ ++MODULE_DESCRIPTION("Video Data Order Adapter"); ++MODULE_AUTHOR("Philipp Zabel "); ++MODULE_ALIAS("platform:imx-vdoa"); ++MODULE_LICENSE("GPL"); +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/imx-vdoa.h b/drivers/media/platform/chips-media/coda/imx-vdoa.h +--- a/drivers/media/platform/chips-media/coda/imx-vdoa.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/imx-vdoa.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,50 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++ * Copyright (C) 2016 Pengutronix ++ */ ++ ++#ifndef IMX_VDOA_H ++#define IMX_VDOA_H ++ ++struct vdoa_data; ++struct vdoa_ctx; ++ ++#if (defined CONFIG_VIDEO_IMX_VDOA || defined CONFIG_VIDEO_IMX_VDOA_MODULE) ++ ++struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa); ++int vdoa_context_configure(struct vdoa_ctx *ctx, ++ unsigned int width, unsigned int height, ++ u32 pixelformat); ++void vdoa_context_destroy(struct vdoa_ctx *ctx); ++ ++void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src); ++int vdoa_wait_for_completion(struct vdoa_ctx *ctx); ++ ++#else ++ ++static inline struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa) ++{ ++ return NULL; ++} ++ ++static inline int vdoa_context_configure(struct vdoa_ctx *ctx, ++ unsigned int width, ++ unsigned int height, ++ u32 pixelformat) ++{ ++ return 0; ++} ++ ++static inline void vdoa_context_destroy(struct vdoa_ctx *ctx) { }; ++ ++static inline void vdoa_device_run(struct vdoa_ctx *ctx, ++ dma_addr_t dst, dma_addr_t src) { }; ++ ++static inline int vdoa_wait_for_completion(struct vdoa_ctx *ctx) ++{ ++ return 0; ++}; ++ ++#endif ++ ++#endif /* IMX_VDOA_H */ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/Kconfig b/drivers/media/platform/chips-media/coda/Kconfig +--- a/drivers/media/platform/chips-media/coda/Kconfig 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/Kconfig 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,18 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++config VIDEO_CODA ++ tristate "Chips&Media Coda multi-standard codec IP" ++ depends on V4L_MEM2MEM_DRIVERS ++ depends on VIDEO_DEV && OF && (ARCH_MXC || COMPILE_TEST) ++ select SRAM ++ select VIDEOBUF2_DMA_CONTIG ++ select VIDEOBUF2_VMALLOC ++ select V4L2_JPEG_HELPER ++ select V4L2_MEM2MEM_DEV ++ select GENERIC_ALLOCATOR ++ help ++ Coda is a range of video codec IPs that supports ++ H.264, MPEG-4, and other video formats. ++ ++config VIDEO_IMX_VDOA ++ def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/Makefile b/drivers/media/platform/chips-media/coda/Makefile +--- a/drivers/media/platform/chips-media/coda/Makefile 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/Makefile 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++coda-vpu-objs := coda-common.o coda-bit.o coda-gdi.o coda-h264.o coda-mpeg2.o coda-mpeg4.o coda-jpeg.o ++ ++obj-$(CONFIG_VIDEO_CODA) += coda-vpu.o ++obj-$(CONFIG_VIDEO_IMX_VDOA) += imx-vdoa.o +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/trace.h b/drivers/media/platform/chips-media/coda/trace.h +--- a/drivers/media/platform/chips-media/coda/trace.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda/trace.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,175 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM coda ++ ++#if !defined(__CODA_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) ++#define __CODA_TRACE_H__ ++ ++#include ++#include ++ ++#include "coda.h" ++ ++TRACE_EVENT(coda_bit_run, ++ TP_PROTO(struct coda_ctx *ctx, int cmd), ++ ++ TP_ARGS(ctx, cmd), ++ ++ TP_STRUCT__entry( ++ __field(int, minor) ++ __field(int, ctx) ++ __field(int, cmd) ++ ), ++ ++ TP_fast_assign( ++ __entry->minor = ctx->fh.vdev->minor; ++ __entry->ctx = ctx->idx; ++ __entry->cmd = cmd; ++ ), ++ ++ TP_printk("minor = %d, ctx = %d, cmd = %d", ++ __entry->minor, __entry->ctx, __entry->cmd) ++); ++ ++TRACE_EVENT(coda_bit_done, ++ TP_PROTO(struct coda_ctx *ctx), ++ ++ TP_ARGS(ctx), ++ ++ TP_STRUCT__entry( ++ __field(int, minor) ++ __field(int, ctx) ++ ), ++ ++ TP_fast_assign( ++ __entry->minor = ctx->fh.vdev->minor; ++ __entry->ctx = ctx->idx; ++ ), ++ ++ TP_printk("minor = %d, ctx = %d", __entry->minor, __entry->ctx) ++); ++ ++DECLARE_EVENT_CLASS(coda_buf_class, ++ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), ++ ++ TP_ARGS(ctx, buf), ++ ++ TP_STRUCT__entry( ++ __field(int, minor) ++ __field(int, index) ++ __field(int, ctx) ++ ), ++ ++ TP_fast_assign( ++ __entry->minor = ctx->fh.vdev->minor; ++ __entry->index = buf->vb2_buf.index; ++ __entry->ctx = ctx->idx; ++ ), ++ ++ TP_printk("minor = %d, index = %d, ctx = %d", ++ __entry->minor, __entry->index, __entry->ctx) ++); ++ ++DEFINE_EVENT(coda_buf_class, coda_enc_pic_run, ++ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), ++ TP_ARGS(ctx, buf) ++); ++ ++DEFINE_EVENT(coda_buf_class, coda_enc_pic_done, ++ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), ++ TP_ARGS(ctx, buf) ++); ++ ++DECLARE_EVENT_CLASS(coda_buf_meta_class, ++ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, ++ struct coda_buffer_meta *meta), ++ ++ TP_ARGS(ctx, buf, meta), ++ ++ TP_STRUCT__entry( ++ __field(int, minor) ++ __field(int, index) ++ __field(int, start) ++ __field(int, end) ++ __field(int, ctx) ++ ), ++ ++ TP_fast_assign( ++ __entry->minor = ctx->fh.vdev->minor; ++ __entry->index = buf->vb2_buf.index; ++ __entry->start = meta->start & ctx->bitstream_fifo.kfifo.mask; ++ __entry->end = meta->end & ctx->bitstream_fifo.kfifo.mask; ++ __entry->ctx = ctx->idx; ++ ), ++ ++ TP_printk("minor = %d, index = %d, start = 0x%x, end = 0x%x, ctx = %d", ++ __entry->minor, __entry->index, __entry->start, __entry->end, ++ __entry->ctx) ++); ++ ++DEFINE_EVENT(coda_buf_meta_class, coda_bit_queue, ++ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, ++ struct coda_buffer_meta *meta), ++ TP_ARGS(ctx, buf, meta) ++); ++ ++DECLARE_EVENT_CLASS(coda_meta_class, ++ TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta), ++ ++ TP_ARGS(ctx, meta), ++ ++ TP_STRUCT__entry( ++ __field(int, minor) ++ __field(int, start) ++ __field(int, end) ++ __field(int, ctx) ++ ), ++ ++ TP_fast_assign( ++ __entry->minor = ctx->fh.vdev->minor; ++ __entry->start = meta ? (meta->start & ++ ctx->bitstream_fifo.kfifo.mask) : 0; ++ __entry->end = meta ? (meta->end & ++ ctx->bitstream_fifo.kfifo.mask) : 0; ++ __entry->ctx = ctx->idx; ++ ), ++ ++ TP_printk("minor = %d, start = 0x%x, end = 0x%x, ctx = %d", ++ __entry->minor, __entry->start, __entry->end, __entry->ctx) ++); ++ ++DEFINE_EVENT(coda_meta_class, coda_dec_pic_run, ++ TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta), ++ TP_ARGS(ctx, meta) ++); ++ ++DEFINE_EVENT(coda_meta_class, coda_dec_pic_done, ++ TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta), ++ TP_ARGS(ctx, meta) ++); ++ ++DEFINE_EVENT(coda_buf_meta_class, coda_dec_rot_done, ++ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, ++ struct coda_buffer_meta *meta), ++ TP_ARGS(ctx, buf, meta) ++); ++ ++DEFINE_EVENT(coda_buf_class, coda_jpeg_run, ++ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), ++ TP_ARGS(ctx, buf) ++); ++ ++DEFINE_EVENT(coda_buf_class, coda_jpeg_done, ++ TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), ++ TP_ARGS(ctx, buf) ++); ++ ++#endif /* __CODA_TRACE_H__ */ ++ ++#undef TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_PATH ../../drivers/media/platform/chips-media/coda ++#undef TRACE_INCLUDE_FILE ++#define TRACE_INCLUDE_FILE trace ++ ++/* This part must be outside protection */ ++#include +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-bit.c b/drivers/media/platform/chips-media/coda-bit.c +--- a/drivers/media/platform/chips-media/coda-bit.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda-bit.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,2666 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Coda multi-standard codec IP - BIT processor functions +- * +- * Copyright (C) 2012 Vista Silicon S.L. +- * Javier Martin, +- * Xavier Duret +- * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "coda.h" +-#include "imx-vdoa.h" +-#define CREATE_TRACE_POINTS +-#include "trace.h" +- +-#define CODA_PARA_BUF_SIZE (10 * 1024) +-#define CODA7_PS_BUF_SIZE 0x28000 +-#define CODA9_PS_SAVE_SIZE (512 * 1024) +- +-#define CODA_DEFAULT_GAMMA 4096 +-#define CODA9_DEFAULT_GAMMA 24576 /* 0.75 * 32768 */ +- +-static void coda_free_bitstream_buffer(struct coda_ctx *ctx); +- +-static inline int coda_is_initialized(struct coda_dev *dev) +-{ +- return coda_read(dev, CODA_REG_BIT_CUR_PC) != 0; +-} +- +-static inline unsigned long coda_isbusy(struct coda_dev *dev) +-{ +- return coda_read(dev, CODA_REG_BIT_BUSY); +-} +- +-static int coda_wait_timeout(struct coda_dev *dev) +-{ +- unsigned long timeout = jiffies + msecs_to_jiffies(1000); +- +- while (coda_isbusy(dev)) { +- if (time_after(jiffies, timeout)) +- return -ETIMEDOUT; +- } +- return 0; +-} +- +-static void coda_command_async(struct coda_ctx *ctx, int cmd) +-{ +- struct coda_dev *dev = ctx->dev; +- +- if (dev->devtype->product == CODA_HX4 || +- dev->devtype->product == CODA_7541 || +- dev->devtype->product == CODA_960) { +- /* Restore context related registers to CODA */ +- coda_write(dev, ctx->bit_stream_param, +- CODA_REG_BIT_BIT_STREAM_PARAM); +- coda_write(dev, ctx->frm_dis_flg, +- CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); +- coda_write(dev, ctx->frame_mem_ctrl, +- CODA_REG_BIT_FRAME_MEM_CTRL); +- coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR); +- } +- +- if (dev->devtype->product == CODA_960) { +- coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); +- coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); +- } +- +- coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); +- +- coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX); +- coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD); +- coda_write(dev, ctx->params.codec_mode_aux, CODA7_REG_BIT_RUN_AUX_STD); +- +- trace_coda_bit_run(ctx, cmd); +- +- coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND); +-} +- +-static int coda_command_sync(struct coda_ctx *ctx, int cmd) +-{ +- struct coda_dev *dev = ctx->dev; +- int ret; +- +- lockdep_assert_held(&dev->coda_mutex); +- +- coda_command_async(ctx, cmd); +- ret = coda_wait_timeout(dev); +- trace_coda_bit_done(ctx); +- +- return ret; +-} +- +-int coda_hw_reset(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- unsigned long timeout; +- unsigned int idx; +- int ret; +- +- lockdep_assert_held(&dev->coda_mutex); +- +- if (!dev->rstc) +- return -ENOENT; +- +- idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX); +- +- if (dev->devtype->product == CODA_960) { +- timeout = jiffies + msecs_to_jiffies(100); +- coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL); +- while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) { +- if (time_after(jiffies, timeout)) +- return -ETIME; +- cpu_relax(); +- } +- } +- +- ret = reset_control_reset(dev->rstc); +- if (ret < 0) +- return ret; +- +- if (dev->devtype->product == CODA_960) +- coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL); +- coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); +- coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); +- ret = coda_wait_timeout(dev); +- coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX); +- +- return ret; +-} +- +-static void coda_kfifo_sync_from_device(struct coda_ctx *ctx) +-{ +- struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; +- struct coda_dev *dev = ctx->dev; +- u32 rd_ptr; +- +- rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); +- kfifo->out = (kfifo->in & ~kfifo->mask) | +- (rd_ptr - ctx->bitstream.paddr); +- if (kfifo->out > kfifo->in) +- kfifo->out -= kfifo->mask + 1; +-} +- +-static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx) +-{ +- struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; +- struct coda_dev *dev = ctx->dev; +- u32 rd_ptr, wr_ptr; +- +- rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask); +- coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); +- wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); +- coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); +-} +- +-static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx) +-{ +- struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo; +- struct coda_dev *dev = ctx->dev; +- u32 wr_ptr; +- +- wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask); +- coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); +-} +- +-static int coda_h264_bitstream_pad(struct coda_ctx *ctx, u32 size) +-{ +- unsigned char *buf; +- u32 n; +- +- if (size < 6) +- size = 6; +- +- buf = kmalloc(size, GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- +- coda_h264_filler_nal(size, buf); +- n = kfifo_in(&ctx->bitstream_fifo, buf, size); +- kfree(buf); +- +- return (n < size) ? -ENOSPC : 0; +-} +- +-int coda_bitstream_flush(struct coda_ctx *ctx) +-{ +- int ret; +- +- if (ctx->inst_type != CODA_INST_DECODER || !ctx->use_bit) +- return 0; +- +- ret = coda_command_sync(ctx, CODA_COMMAND_DEC_BUF_FLUSH); +- if (ret < 0) { +- v4l2_err(&ctx->dev->v4l2_dev, "failed to flush bitstream\n"); +- return ret; +- } +- +- kfifo_init(&ctx->bitstream_fifo, ctx->bitstream.vaddr, +- ctx->bitstream.size); +- coda_kfifo_sync_to_device_full(ctx); +- +- return 0; +-} +- +-static int coda_bitstream_queue(struct coda_ctx *ctx, const u8 *buf, u32 size) +-{ +- u32 n = kfifo_in(&ctx->bitstream_fifo, buf, size); +- +- return (n < size) ? -ENOSPC : 0; +-} +- +-static u32 coda_buffer_parse_headers(struct coda_ctx *ctx, +- struct vb2_v4l2_buffer *src_buf, +- u32 payload) +-{ +- u8 *vaddr = vb2_plane_vaddr(&src_buf->vb2_buf, 0); +- u32 size = 0; +- +- switch (ctx->codec->src_fourcc) { +- case V4L2_PIX_FMT_MPEG2: +- size = coda_mpeg2_parse_headers(ctx, vaddr, payload); +- break; +- case V4L2_PIX_FMT_MPEG4: +- size = coda_mpeg4_parse_headers(ctx, vaddr, payload); +- break; +- default: +- break; +- } +- +- return size; +-} +- +-static bool coda_bitstream_try_queue(struct coda_ctx *ctx, +- struct vb2_v4l2_buffer *src_buf) +-{ +- unsigned long payload = vb2_get_plane_payload(&src_buf->vb2_buf, 0); +- u8 *vaddr = vb2_plane_vaddr(&src_buf->vb2_buf, 0); +- int ret; +- int i; +- +- if (coda_get_bitstream_payload(ctx) + payload + 512 >= +- ctx->bitstream.size) +- return false; +- +- if (!vaddr) { +- v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n"); +- return true; +- } +- +- if (ctx->qsequence == 0 && payload < 512) { +- /* +- * Add padding after the first buffer, if it is too small to be +- * fetched by the CODA, by repeating the headers. Without +- * repeated headers, or the first frame already queued, decoder +- * sequence initialization fails with error code 0x2000 on i.MX6 +- * or error code 0x1 on i.MX51. +- */ +- u32 header_size = coda_buffer_parse_headers(ctx, src_buf, +- payload); +- +- if (header_size) { +- coda_dbg(1, ctx, "pad with %u-byte header\n", +- header_size); +- for (i = payload; i < 512; i += header_size) { +- ret = coda_bitstream_queue(ctx, vaddr, +- header_size); +- if (ret < 0) { +- v4l2_err(&ctx->dev->v4l2_dev, +- "bitstream buffer overflow\n"); +- return false; +- } +- if (ctx->dev->devtype->product == CODA_960) +- break; +- } +- } else { +- coda_dbg(1, ctx, +- "could not parse header, sequence initialization might fail\n"); +- } +- +- /* Add padding before the first buffer, if it is too small */ +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264) +- coda_h264_bitstream_pad(ctx, 512 - payload); +- } +- +- ret = coda_bitstream_queue(ctx, vaddr, payload); +- if (ret < 0) { +- v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n"); +- return false; +- } +- +- src_buf->sequence = ctx->qsequence++; +- +- /* Sync read pointer to device */ +- if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev)) +- coda_kfifo_sync_to_device_write(ctx); +- +- /* Set the stream-end flag after the last buffer is queued */ +- if (src_buf->flags & V4L2_BUF_FLAG_LAST) +- coda_bit_stream_end_flag(ctx); +- ctx->hold = false; +- +- return true; +-} +- +-void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list) +-{ +- struct vb2_v4l2_buffer *src_buf; +- struct coda_buffer_meta *meta; +- u32 start; +- +- lockdep_assert_held(&ctx->bitstream_mutex); +- +- if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) +- return; +- +- while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) { +- /* +- * Only queue two JPEGs into the bitstream buffer to keep +- * latency low. We need at least one complete buffer and the +- * header of another buffer (for prescan) in the bitstream. +- */ +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG && +- ctx->num_metas > 1) +- break; +- +- if (ctx->num_internal_frames && +- ctx->num_metas >= ctx->num_internal_frames) { +- meta = list_first_entry(&ctx->buffer_meta_list, +- struct coda_buffer_meta, list); +- +- /* +- * If we managed to fill in at least a full reorder +- * window of buffers (num_internal_frames is a +- * conservative estimate for this) and the bitstream +- * prefetcher has at least 2 256 bytes periods beyond +- * the first buffer to fetch, we can safely stop queuing +- * in order to limit the decoder drain latency. +- */ +- if (coda_bitstream_can_fetch_past(ctx, meta->end)) +- break; +- } +- +- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); +- +- /* Drop frames that do not start/end with a SOI/EOI markers */ +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG && +- !coda_jpeg_check_buffer(ctx, &src_buf->vb2_buf)) { +- v4l2_err(&ctx->dev->v4l2_dev, +- "dropping invalid JPEG frame %d\n", +- ctx->qsequence); +- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); +- if (buffer_list) { +- struct v4l2_m2m_buffer *m2m_buf; +- +- m2m_buf = container_of(src_buf, +- struct v4l2_m2m_buffer, +- vb); +- list_add_tail(&m2m_buf->list, buffer_list); +- } else { +- v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); +- } +- continue; +- } +- +- /* Dump empty buffers */ +- if (!vb2_get_plane_payload(&src_buf->vb2_buf, 0)) { +- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); +- v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); +- continue; +- } +- +- /* Buffer start position */ +- start = ctx->bitstream_fifo.kfifo.in; +- +- if (coda_bitstream_try_queue(ctx, src_buf)) { +- /* +- * Source buffer is queued in the bitstream ringbuffer; +- * queue the timestamp and mark source buffer as done +- */ +- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); +- +- meta = kmalloc(sizeof(*meta), GFP_KERNEL); +- if (meta) { +- meta->sequence = src_buf->sequence; +- meta->timecode = src_buf->timecode; +- meta->timestamp = src_buf->vb2_buf.timestamp; +- meta->start = start; +- meta->end = ctx->bitstream_fifo.kfifo.in; +- meta->last = src_buf->flags & V4L2_BUF_FLAG_LAST; +- if (meta->last) +- coda_dbg(1, ctx, "marking last meta"); +- spin_lock(&ctx->buffer_meta_lock); +- list_add_tail(&meta->list, +- &ctx->buffer_meta_list); +- ctx->num_metas++; +- spin_unlock(&ctx->buffer_meta_lock); +- +- trace_coda_bit_queue(ctx, src_buf, meta); +- } +- +- if (buffer_list) { +- struct v4l2_m2m_buffer *m2m_buf; +- +- m2m_buf = container_of(src_buf, +- struct v4l2_m2m_buffer, +- vb); +- list_add_tail(&m2m_buf->list, buffer_list); +- } else { +- v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); +- } +- } else { +- break; +- } +- } +-} +- +-void coda_bit_stream_end_flag(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- +- ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; +- +- /* If this context is currently running, update the hardware flag */ +- if ((dev->devtype->product == CODA_960) && +- coda_isbusy(dev) && +- (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) { +- coda_write(dev, ctx->bit_stream_param, +- CODA_REG_BIT_BIT_STREAM_PARAM); +- } +-} +- +-static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value) +-{ +- struct coda_dev *dev = ctx->dev; +- u32 *p = ctx->parabuf.vaddr; +- +- if (dev->devtype->product == CODA_DX6) +- p[index] = value; +- else +- p[index ^ 1] = value; +-} +- +-static inline int coda_alloc_context_buf(struct coda_ctx *ctx, +- struct coda_aux_buf *buf, size_t size, +- const char *name) +-{ +- return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry); +-} +- +- +-static void coda_free_framebuffers(struct coda_ctx *ctx) +-{ +- int i; +- +- for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) +- coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i].buf); +-} +- +-static int coda_alloc_framebuffers(struct coda_ctx *ctx, +- struct coda_q_data *q_data, u32 fourcc) +-{ +- struct coda_dev *dev = ctx->dev; +- unsigned int ysize, ycbcr_size; +- int ret; +- int i; +- +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || +- ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 || +- ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 || +- ctx->codec->dst_fourcc == V4L2_PIX_FMT_MPEG4) +- ysize = round_up(q_data->rect.width, 16) * +- round_up(q_data->rect.height, 16); +- else +- ysize = round_up(q_data->rect.width, 8) * q_data->rect.height; +- +- if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) +- ycbcr_size = round_up(ysize, 4096) + ysize / 2; +- else +- ycbcr_size = ysize + ysize / 2; +- +- /* Allocate frame buffers */ +- for (i = 0; i < ctx->num_internal_frames; i++) { +- size_t size = ycbcr_size; +- char *name; +- +- /* Add space for mvcol buffers */ +- if (dev->devtype->product != CODA_DX6 && +- (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || +- (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0))) +- size += ysize / 4; +- name = kasprintf(GFP_KERNEL, "fb%d", i); +- if (!name) { +- coda_free_framebuffers(ctx); +- return -ENOMEM; +- } +- ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i].buf, +- size, name); +- kfree(name); +- if (ret < 0) { +- coda_free_framebuffers(ctx); +- return ret; +- } +- } +- +- /* Register frame buffers in the parameter buffer */ +- for (i = 0; i < ctx->num_internal_frames; i++) { +- u32 y, cb, cr, mvcol; +- +- /* Start addresses of Y, Cb, Cr planes */ +- y = ctx->internal_frames[i].buf.paddr; +- cb = y + ysize; +- cr = y + ysize + ysize/4; +- mvcol = y + ysize + ysize/4 + ysize/4; +- if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) { +- cb = round_up(cb, 4096); +- mvcol = cb + ysize/2; +- cr = 0; +- /* Packed 20-bit MSB of base addresses */ +- /* YYYYYCCC, CCyyyyyc, cccc.... */ +- y = (y & 0xfffff000) | cb >> 20; +- cb = (cb & 0x000ff000) << 12; +- } +- coda_parabuf_write(ctx, i * 3 + 0, y); +- coda_parabuf_write(ctx, i * 3 + 1, cb); +- coda_parabuf_write(ctx, i * 3 + 2, cr); +- +- if (dev->devtype->product == CODA_DX6) +- continue; +- +- /* mvcol buffer for h.264 and mpeg4 */ +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264) +- coda_parabuf_write(ctx, 96 + i, mvcol); +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0) +- coda_parabuf_write(ctx, 97, mvcol); +- } +- +- return 0; +-} +- +-static void coda_free_context_buffers(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- +- coda_free_aux_buf(dev, &ctx->slicebuf); +- coda_free_aux_buf(dev, &ctx->psbuf); +- if (dev->devtype->product != CODA_DX6) +- coda_free_aux_buf(dev, &ctx->workbuf); +- coda_free_aux_buf(dev, &ctx->parabuf); +-} +- +-static int coda_alloc_context_buffers(struct coda_ctx *ctx, +- struct coda_q_data *q_data) +-{ +- struct coda_dev *dev = ctx->dev; +- size_t size; +- int ret; +- +- if (!ctx->parabuf.vaddr) { +- ret = coda_alloc_context_buf(ctx, &ctx->parabuf, +- CODA_PARA_BUF_SIZE, "parabuf"); +- if (ret < 0) +- return ret; +- } +- +- if (dev->devtype->product == CODA_DX6) +- return 0; +- +- if (!ctx->slicebuf.vaddr && q_data->fourcc == V4L2_PIX_FMT_H264) { +- /* worst case slice size */ +- size = (DIV_ROUND_UP(q_data->rect.width, 16) * +- DIV_ROUND_UP(q_data->rect.height, 16)) * 3200 / 8 + 512; +- ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size, +- "slicebuf"); +- if (ret < 0) +- goto err; +- } +- +- if (!ctx->psbuf.vaddr && (dev->devtype->product == CODA_HX4 || +- dev->devtype->product == CODA_7541)) { +- ret = coda_alloc_context_buf(ctx, &ctx->psbuf, +- CODA7_PS_BUF_SIZE, "psbuf"); +- if (ret < 0) +- goto err; +- } +- +- if (!ctx->workbuf.vaddr) { +- size = dev->devtype->workbuf_size; +- if (dev->devtype->product == CODA_960 && +- q_data->fourcc == V4L2_PIX_FMT_H264) +- size += CODA9_PS_SAVE_SIZE; +- ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size, +- "workbuf"); +- if (ret < 0) +- goto err; +- } +- +- return 0; +- +-err: +- coda_free_context_buffers(ctx); +- return ret; +-} +- +-static int coda_encode_header(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, +- int header_code, u8 *header, int *size) +-{ +- struct vb2_buffer *vb = &buf->vb2_buf; +- struct coda_dev *dev = ctx->dev; +- struct coda_q_data *q_data_src; +- struct v4l2_rect *r; +- size_t bufsize; +- int ret; +- int i; +- +- if (dev->devtype->product == CODA_960) +- memset(vb2_plane_vaddr(vb, 0), 0, 64); +- +- coda_write(dev, vb2_dma_contig_plane_dma_addr(vb, 0), +- CODA_CMD_ENC_HEADER_BB_START); +- bufsize = vb2_plane_size(vb, 0); +- if (dev->devtype->product == CODA_960) +- bufsize /= 1024; +- coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE); +- if (dev->devtype->product == CODA_960 && +- ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 && +- header_code == CODA_HEADER_H264_SPS) { +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- r = &q_data_src->rect; +- +- if (r->width % 16 || r->height % 16) { +- u32 crop_right = round_up(r->width, 16) - r->width; +- u32 crop_bottom = round_up(r->height, 16) - r->height; +- +- coda_write(dev, crop_right, +- CODA9_CMD_ENC_HEADER_FRAME_CROP_H); +- coda_write(dev, crop_bottom, +- CODA9_CMD_ENC_HEADER_FRAME_CROP_V); +- header_code |= CODA9_HEADER_FRAME_CROP; +- } +- } +- coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE); +- ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER); +- if (ret < 0) { +- v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n"); +- return ret; +- } +- +- if (dev->devtype->product == CODA_960) { +- for (i = 63; i > 0; i--) +- if (((char *)vb2_plane_vaddr(vb, 0))[i] != 0) +- break; +- *size = i + 1; +- } else { +- *size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) - +- coda_read(dev, CODA_CMD_ENC_HEADER_BB_START); +- } +- memcpy(header, vb2_plane_vaddr(vb, 0), *size); +- +- return 0; +-} +- +-static u32 coda_slice_mode(struct coda_ctx *ctx) +-{ +- int size, unit; +- +- switch (ctx->params.slice_mode) { +- case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE: +- default: +- return 0; +- case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB: +- size = ctx->params.slice_max_mb; +- unit = 1; +- break; +- case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES: +- size = ctx->params.slice_max_bits; +- unit = 0; +- break; +- } +- +- return ((size & CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET) | +- ((unit & CODA_SLICING_UNIT_MASK) << CODA_SLICING_UNIT_OFFSET) | +- ((1 & CODA_SLICING_MODE_MASK) << CODA_SLICING_MODE_OFFSET); +-} +- +-static int coda_enc_param_change(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- u32 change_enable = 0; +- u32 success; +- int ret; +- +- if (ctx->params.gop_size_changed) { +- change_enable |= CODA_PARAM_CHANGE_RC_GOP; +- coda_write(dev, ctx->params.gop_size, +- CODA_CMD_ENC_PARAM_RC_GOP); +- ctx->gopcounter = ctx->params.gop_size - 1; +- ctx->params.gop_size_changed = false; +- } +- if (ctx->params.h264_intra_qp_changed) { +- coda_dbg(1, ctx, "parameter change: intra Qp %u\n", +- ctx->params.h264_intra_qp); +- +- if (ctx->params.bitrate) { +- change_enable |= CODA_PARAM_CHANGE_RC_INTRA_QP; +- coda_write(dev, ctx->params.h264_intra_qp, +- CODA_CMD_ENC_PARAM_RC_INTRA_QP); +- } +- ctx->params.h264_intra_qp_changed = false; +- } +- if (ctx->params.bitrate_changed) { +- coda_dbg(1, ctx, "parameter change: bitrate %u kbit/s\n", +- ctx->params.bitrate); +- change_enable |= CODA_PARAM_CHANGE_RC_BITRATE; +- coda_write(dev, ctx->params.bitrate, +- CODA_CMD_ENC_PARAM_RC_BITRATE); +- ctx->params.bitrate_changed = false; +- } +- if (ctx->params.framerate_changed) { +- coda_dbg(1, ctx, "parameter change: frame rate %u/%u Hz\n", +- ctx->params.framerate & 0xffff, +- (ctx->params.framerate >> 16) + 1); +- change_enable |= CODA_PARAM_CHANGE_RC_FRAME_RATE; +- coda_write(dev, ctx->params.framerate, +- CODA_CMD_ENC_PARAM_RC_FRAME_RATE); +- ctx->params.framerate_changed = false; +- } +- if (ctx->params.intra_refresh_changed) { +- coda_dbg(1, ctx, "parameter change: intra refresh MBs %u\n", +- ctx->params.intra_refresh); +- change_enable |= CODA_PARAM_CHANGE_INTRA_MB_NUM; +- coda_write(dev, ctx->params.intra_refresh, +- CODA_CMD_ENC_PARAM_INTRA_MB_NUM); +- ctx->params.intra_refresh_changed = false; +- } +- if (ctx->params.slice_mode_changed) { +- change_enable |= CODA_PARAM_CHANGE_SLICE_MODE; +- coda_write(dev, coda_slice_mode(ctx), +- CODA_CMD_ENC_PARAM_SLICE_MODE); +- ctx->params.slice_mode_changed = false; +- } +- +- if (!change_enable) +- return 0; +- +- coda_write(dev, change_enable, CODA_CMD_ENC_PARAM_CHANGE_ENABLE); +- +- ret = coda_command_sync(ctx, CODA_COMMAND_RC_CHANGE_PARAMETER); +- if (ret < 0) +- return ret; +- +- success = coda_read(dev, CODA_RET_ENC_PARAM_CHANGE_SUCCESS); +- if (success != 1) +- coda_dbg(1, ctx, "parameter change failed: %u\n", success); +- +- return 0; +-} +- +-static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size) +-{ +- phys_addr_t ret; +- +- size = round_up(size, 1024); +- if (size > iram->remaining) +- return 0; +- iram->remaining -= size; +- +- ret = iram->next_paddr; +- iram->next_paddr += size; +- +- return ret; +-} +- +-static void coda_setup_iram(struct coda_ctx *ctx) +-{ +- struct coda_iram_info *iram_info = &ctx->iram_info; +- struct coda_dev *dev = ctx->dev; +- int w64, w128; +- int mb_width; +- int dbk_bits; +- int bit_bits; +- int ip_bits; +- int me_bits; +- +- memset(iram_info, 0, sizeof(*iram_info)); +- iram_info->next_paddr = dev->iram.paddr; +- iram_info->remaining = dev->iram.size; +- +- if (!dev->iram.vaddr) +- return; +- +- switch (dev->devtype->product) { +- case CODA_HX4: +- dbk_bits = CODA7_USE_HOST_DBK_ENABLE; +- bit_bits = CODA7_USE_HOST_BIT_ENABLE; +- ip_bits = CODA7_USE_HOST_IP_ENABLE; +- me_bits = CODA7_USE_HOST_ME_ENABLE; +- break; +- case CODA_7541: +- dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE; +- bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE; +- ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; +- me_bits = CODA7_USE_HOST_ME_ENABLE | CODA7_USE_ME_ENABLE; +- break; +- case CODA_960: +- dbk_bits = CODA9_USE_HOST_DBK_ENABLE | CODA9_USE_DBK_ENABLE; +- bit_bits = CODA9_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE; +- ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE; +- me_bits = 0; +- break; +- default: /* CODA_DX6 */ +- return; +- } +- +- if (ctx->inst_type == CODA_INST_ENCODER) { +- struct coda_q_data *q_data_src; +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- mb_width = DIV_ROUND_UP(q_data_src->rect.width, 16); +- w128 = mb_width * 128; +- w64 = mb_width * 64; +- +- /* Prioritize in case IRAM is too small for everything */ +- if (dev->devtype->product == CODA_HX4 || +- dev->devtype->product == CODA_7541) { +- iram_info->search_ram_size = round_up(mb_width * 16 * +- 36 + 2048, 1024); +- iram_info->search_ram_paddr = coda_iram_alloc(iram_info, +- iram_info->search_ram_size); +- if (!iram_info->search_ram_paddr) { +- pr_err("IRAM is smaller than the search ram size\n"); +- goto out; +- } +- iram_info->axi_sram_use |= me_bits; +- } +- +- /* Only H.264BP and H.263P3 are considered */ +- iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64); +- iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64); +- if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) +- goto out; +- iram_info->axi_sram_use |= dbk_bits; +- +- iram_info->buf_bit_use = coda_iram_alloc(iram_info, w128); +- if (!iram_info->buf_bit_use) +- goto out; +- iram_info->axi_sram_use |= bit_bits; +- +- iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, w128); +- if (!iram_info->buf_ip_ac_dc_use) +- goto out; +- iram_info->axi_sram_use |= ip_bits; +- +- /* OVL and BTP disabled for encoder */ +- } else if (ctx->inst_type == CODA_INST_DECODER) { +- struct coda_q_data *q_data_dst; +- +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- mb_width = DIV_ROUND_UP(q_data_dst->width, 16); +- w128 = mb_width * 128; +- +- iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w128); +- iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w128); +- if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) +- goto out; +- iram_info->axi_sram_use |= dbk_bits; +- +- iram_info->buf_bit_use = coda_iram_alloc(iram_info, w128); +- if (!iram_info->buf_bit_use) +- goto out; +- iram_info->axi_sram_use |= bit_bits; +- +- iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, w128); +- if (!iram_info->buf_ip_ac_dc_use) +- goto out; +- iram_info->axi_sram_use |= ip_bits; +- +- /* OVL and BTP unused as there is no VC1 support yet */ +- } +- +-out: +- if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)) +- coda_dbg(1, ctx, "IRAM smaller than needed\n"); +- +- if (dev->devtype->product == CODA_HX4 || +- dev->devtype->product == CODA_7541) { +- /* TODO - Enabling these causes picture errors on CODA7541 */ +- if (ctx->inst_type == CODA_INST_DECODER) { +- /* fw 1.4.50 */ +- iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE | +- CODA7_USE_IP_ENABLE); +- } else { +- /* fw 13.4.29 */ +- iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE | +- CODA7_USE_HOST_DBK_ENABLE | +- CODA7_USE_IP_ENABLE | +- CODA7_USE_DBK_ENABLE); +- } +- } +-} +- +-static u32 coda_supported_firmwares[] = { +- CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5), +- CODA_FIRMWARE_VERNUM(CODA_HX4, 1, 4, 50), +- CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50), +- CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5), +- CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 9), +- CODA_FIRMWARE_VERNUM(CODA_960, 2, 3, 10), +- CODA_FIRMWARE_VERNUM(CODA_960, 3, 1, 1), +-}; +- +-static bool coda_firmware_supported(u32 vernum) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++) +- if (vernum == coda_supported_firmwares[i]) +- return true; +- return false; +-} +- +-int coda_check_firmware(struct coda_dev *dev) +-{ +- u16 product, major, minor, release; +- u32 data; +- int ret; +- +- ret = clk_prepare_enable(dev->clk_per); +- if (ret) +- goto err_clk_per; +- +- ret = clk_prepare_enable(dev->clk_ahb); +- if (ret) +- goto err_clk_ahb; +- +- coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM); +- coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY); +- coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX); +- coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD); +- coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND); +- if (coda_wait_timeout(dev)) { +- v4l2_err(&dev->v4l2_dev, "firmware get command error\n"); +- ret = -EIO; +- goto err_run_cmd; +- } +- +- if (dev->devtype->product == CODA_960) { +- data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV); +- v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n", +- data); +- } +- +- /* Check we are compatible with the loaded firmware */ +- data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM); +- product = CODA_FIRMWARE_PRODUCT(data); +- major = CODA_FIRMWARE_MAJOR(data); +- minor = CODA_FIRMWARE_MINOR(data); +- release = CODA_FIRMWARE_RELEASE(data); +- +- clk_disable_unprepare(dev->clk_per); +- clk_disable_unprepare(dev->clk_ahb); +- +- if (product != dev->devtype->product) { +- v4l2_err(&dev->v4l2_dev, +- "Wrong firmware. Hw: %s, Fw: %s, Version: %u.%u.%u\n", +- coda_product_name(dev->devtype->product), +- coda_product_name(product), major, minor, release); +- return -EINVAL; +- } +- +- v4l2_info(&dev->v4l2_dev, "Initialized %s.\n", +- coda_product_name(product)); +- +- if (coda_firmware_supported(data)) { +- v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n", +- major, minor, release); +- } else { +- v4l2_warn(&dev->v4l2_dev, +- "Unsupported firmware version: %u.%u.%u\n", +- major, minor, release); +- } +- +- return 0; +- +-err_run_cmd: +- clk_disable_unprepare(dev->clk_ahb); +-err_clk_ahb: +- clk_disable_unprepare(dev->clk_per); +-err_clk_per: +- return ret; +-} +- +-static void coda9_set_frame_cache(struct coda_ctx *ctx, u32 fourcc) +-{ +- u32 cache_size, cache_config; +- +- if (ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) { +- /* Luma 2x0 page, 2x6 cache, chroma 2x0 page, 2x4 cache size */ +- cache_size = 0x20262024; +- cache_config = 2 << CODA9_CACHE_PAGEMERGE_OFFSET; +- } else { +- /* Luma 0x2 page, 4x4 cache, chroma 0x2 page, 4x3 cache size */ +- cache_size = 0x02440243; +- cache_config = 1 << CODA9_CACHE_PAGEMERGE_OFFSET; +- } +- coda_write(ctx->dev, cache_size, CODA9_CMD_SET_FRAME_CACHE_SIZE); +- if (fourcc == V4L2_PIX_FMT_NV12 || fourcc == V4L2_PIX_FMT_YUYV) { +- cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | +- 16 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET | +- 0 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET; +- } else { +- cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET | +- 8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET | +- 8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET; +- } +- coda_write(ctx->dev, cache_config, CODA9_CMD_SET_FRAME_CACHE_CONFIG); +-} +- +-/* +- * Encoder context operations +- */ +- +-static int coda_encoder_reqbufs(struct coda_ctx *ctx, +- struct v4l2_requestbuffers *rb) +-{ +- struct coda_q_data *q_data_src; +- int ret; +- +- if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) +- return 0; +- +- if (rb->count) { +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- ret = coda_alloc_context_buffers(ctx, q_data_src); +- if (ret < 0) +- return ret; +- } else { +- coda_free_context_buffers(ctx); +- } +- +- return 0; +-} +- +-static int coda_start_encoding(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- struct v4l2_device *v4l2_dev = &dev->v4l2_dev; +- struct coda_q_data *q_data_src, *q_data_dst; +- u32 bitstream_buf, bitstream_size; +- struct vb2_v4l2_buffer *buf; +- int gamma, ret, value; +- u32 dst_fourcc; +- int num_fb; +- u32 stride; +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- dst_fourcc = q_data_dst->fourcc; +- +- buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +- bitstream_buf = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0); +- bitstream_size = q_data_dst->sizeimage; +- +- if (!coda_is_initialized(dev)) { +- v4l2_err(v4l2_dev, "coda is not initialized.\n"); +- return -EFAULT; +- } +- +- if (dst_fourcc == V4L2_PIX_FMT_JPEG) { +- if (!ctx->params.jpeg_qmat_tab[0]) { +- ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[0]) +- return -ENOMEM; +- } +- if (!ctx->params.jpeg_qmat_tab[1]) { +- ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[1]) +- return -ENOMEM; +- } +- coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); +- } +- +- mutex_lock(&dev->coda_mutex); +- +- coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); +- coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->reg_idx)); +- coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); +- switch (dev->devtype->product) { +- case CODA_DX6: +- coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN | +- CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); +- break; +- case CODA_960: +- coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); +- fallthrough; +- case CODA_HX4: +- case CODA_7541: +- coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN | +- CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL); +- break; +- } +- +- ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) | +- CODA9_FRAME_TILED2LINEAR); +- if (q_data_src->fourcc == V4L2_PIX_FMT_NV12) +- ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE; +- if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) +- ctx->frame_mem_ctrl |= (0x3 << 9) | CODA9_FRAME_TILED2LINEAR; +- coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL); +- +- if (dev->devtype->product == CODA_DX6) { +- /* Configure the coda */ +- coda_write(dev, dev->iram.paddr, +- CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR); +- } +- +- /* Could set rotation here if needed */ +- value = 0; +- switch (dev->devtype->product) { +- case CODA_DX6: +- value = (q_data_src->rect.width & CODADX6_PICWIDTH_MASK) +- << CODADX6_PICWIDTH_OFFSET; +- value |= (q_data_src->rect.height & CODADX6_PICHEIGHT_MASK) +- << CODA_PICHEIGHT_OFFSET; +- break; +- case CODA_HX4: +- case CODA_7541: +- if (dst_fourcc == V4L2_PIX_FMT_H264) { +- value = (round_up(q_data_src->rect.width, 16) & +- CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET; +- value |= (round_up(q_data_src->rect.height, 16) & +- CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET; +- break; +- } +- fallthrough; +- case CODA_960: +- value = (q_data_src->rect.width & CODA7_PICWIDTH_MASK) +- << CODA7_PICWIDTH_OFFSET; +- value |= (q_data_src->rect.height & CODA7_PICHEIGHT_MASK) +- << CODA_PICHEIGHT_OFFSET; +- } +- coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE); +- if (dst_fourcc == V4L2_PIX_FMT_JPEG) +- ctx->params.framerate = 0; +- coda_write(dev, ctx->params.framerate, +- CODA_CMD_ENC_SEQ_SRC_F_RATE); +- +- ctx->params.codec_mode = ctx->codec->mode; +- switch (dst_fourcc) { +- case V4L2_PIX_FMT_MPEG4: +- if (dev->devtype->product == CODA_960) +- coda_write(dev, CODA9_STD_MPEG4, +- CODA_CMD_ENC_SEQ_COD_STD); +- else +- coda_write(dev, CODA_STD_MPEG4, +- CODA_CMD_ENC_SEQ_COD_STD); +- coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA); +- break; +- case V4L2_PIX_FMT_H264: +- if (dev->devtype->product == CODA_960) +- coda_write(dev, CODA9_STD_H264, +- CODA_CMD_ENC_SEQ_COD_STD); +- else +- coda_write(dev, CODA_STD_H264, +- CODA_CMD_ENC_SEQ_COD_STD); +- value = ((ctx->params.h264_disable_deblocking_filter_idc & +- CODA_264PARAM_DISABLEDEBLK_MASK) << +- CODA_264PARAM_DISABLEDEBLK_OFFSET) | +- ((ctx->params.h264_slice_alpha_c0_offset_div2 & +- CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) << +- CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) | +- ((ctx->params.h264_slice_beta_offset_div2 & +- CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) << +- CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET) | +- (ctx->params.h264_constrained_intra_pred_flag << +- CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET) | +- (ctx->params.h264_chroma_qp_index_offset & +- CODA_264PARAM_CHROMAQPOFFSET_MASK); +- coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA); +- break; +- case V4L2_PIX_FMT_JPEG: +- coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_PARA); +- coda_write(dev, ctx->params.jpeg_restart_interval, +- CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL); +- coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_EN); +- coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE); +- coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET); +- +- coda_jpeg_write_tables(ctx); +- break; +- default: +- v4l2_err(v4l2_dev, +- "dst format (0x%08x) invalid.\n", dst_fourcc); +- ret = -EINVAL; +- goto out; +- } +- +- /* +- * slice mode and GOP size registers are used for thumb size/offset +- * in JPEG mode +- */ +- if (dst_fourcc != V4L2_PIX_FMT_JPEG) { +- value = coda_slice_mode(ctx); +- coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE); +- value = ctx->params.gop_size; +- coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE); +- } +- +- if (ctx->params.bitrate && (ctx->params.frame_rc_enable || +- ctx->params.mb_rc_enable)) { +- ctx->params.bitrate_changed = false; +- ctx->params.h264_intra_qp_changed = false; +- +- /* Rate control enabled */ +- value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK) +- << CODA_RATECONTROL_BITRATE_OFFSET; +- value |= 1 & CODA_RATECONTROL_ENABLE_MASK; +- value |= (ctx->params.vbv_delay & +- CODA_RATECONTROL_INITIALDELAY_MASK) +- << CODA_RATECONTROL_INITIALDELAY_OFFSET; +- if (dev->devtype->product == CODA_960) +- value |= BIT(31); /* disable autoskip */ +- } else { +- value = 0; +- } +- coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA); +- +- coda_write(dev, ctx->params.vbv_size, CODA_CMD_ENC_SEQ_RC_BUF_SIZE); +- coda_write(dev, ctx->params.intra_refresh, +- CODA_CMD_ENC_SEQ_INTRA_REFRESH); +- +- coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START); +- coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE); +- +- +- value = 0; +- if (dev->devtype->product == CODA_960) +- gamma = CODA9_DEFAULT_GAMMA; +- else +- gamma = CODA_DEFAULT_GAMMA; +- if (gamma > 0) { +- coda_write(dev, (gamma & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET, +- CODA_CMD_ENC_SEQ_RC_GAMMA); +- } +- +- if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) { +- coda_write(dev, +- ctx->params.h264_min_qp << CODA_QPMIN_OFFSET | +- ctx->params.h264_max_qp << CODA_QPMAX_OFFSET, +- CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX); +- } +- if (dev->devtype->product == CODA_960) { +- if (ctx->params.h264_max_qp) +- value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET; +- if (CODA_DEFAULT_GAMMA > 0) +- value |= 1 << CODA9_OPTION_GAMMA_OFFSET; +- } else { +- if (CODA_DEFAULT_GAMMA > 0) { +- if (dev->devtype->product == CODA_DX6) +- value |= 1 << CODADX6_OPTION_GAMMA_OFFSET; +- else +- value |= 1 << CODA7_OPTION_GAMMA_OFFSET; +- } +- if (ctx->params.h264_min_qp) +- value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET; +- if (ctx->params.h264_max_qp) +- value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET; +- } +- coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION); +- +- if (ctx->params.frame_rc_enable && !ctx->params.mb_rc_enable) +- value = 1; +- else +- value = 0; +- coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE); +- +- coda_setup_iram(ctx); +- +- if (dst_fourcc == V4L2_PIX_FMT_H264) { +- switch (dev->devtype->product) { +- case CODA_DX6: +- value = FMO_SLICE_SAVE_BUF_SIZE << 7; +- coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO); +- break; +- case CODA_HX4: +- case CODA_7541: +- coda_write(dev, ctx->iram_info.search_ram_paddr, +- CODA7_CMD_ENC_SEQ_SEARCH_BASE); +- coda_write(dev, ctx->iram_info.search_ram_size, +- CODA7_CMD_ENC_SEQ_SEARCH_SIZE); +- break; +- case CODA_960: +- coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION); +- coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT); +- } +- } +- +- ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT); +- if (ret < 0) { +- v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); +- goto out; +- } +- +- if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) { +- v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n"); +- ret = -EFAULT; +- goto out; +- } +- ctx->initialized = 1; +- +- if (dst_fourcc != V4L2_PIX_FMT_JPEG) { +- if (dev->devtype->product == CODA_960) +- ctx->num_internal_frames = 4; +- else +- ctx->num_internal_frames = 2; +- ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc); +- if (ret < 0) { +- v4l2_err(v4l2_dev, "failed to allocate framebuffers\n"); +- goto out; +- } +- num_fb = 2; +- stride = q_data_src->bytesperline; +- } else { +- ctx->num_internal_frames = 0; +- num_fb = 0; +- stride = 0; +- } +- coda_write(dev, num_fb, CODA_CMD_SET_FRAME_BUF_NUM); +- coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE); +- +- if (dev->devtype->product == CODA_HX4 || +- dev->devtype->product == CODA_7541) { +- coda_write(dev, q_data_src->bytesperline, +- CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE); +- } +- if (dev->devtype->product != CODA_DX6) { +- coda_write(dev, ctx->iram_info.buf_bit_use, +- CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); +- coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, +- CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); +- coda_write(dev, ctx->iram_info.buf_dbk_y_use, +- CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); +- coda_write(dev, ctx->iram_info.buf_dbk_c_use, +- CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); +- coda_write(dev, ctx->iram_info.buf_ovl_use, +- CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); +- if (dev->devtype->product == CODA_960) { +- coda_write(dev, ctx->iram_info.buf_btp_use, +- CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); +- +- coda9_set_frame_cache(ctx, q_data_src->fourcc); +- +- /* FIXME */ +- coda_write(dev, ctx->internal_frames[2].buf.paddr, +- CODA9_CMD_SET_FRAME_SUBSAMP_A); +- coda_write(dev, ctx->internal_frames[3].buf.paddr, +- CODA9_CMD_SET_FRAME_SUBSAMP_B); +- } +- } +- +- ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF); +- if (ret < 0) { +- v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n"); +- goto out; +- } +- +- coda_dbg(1, ctx, "start encoding %dx%d %4.4s->%4.4s @ %d/%d Hz\n", +- q_data_src->rect.width, q_data_src->rect.height, +- (char *)&ctx->codec->src_fourcc, (char *)&dst_fourcc, +- ctx->params.framerate & 0xffff, +- (ctx->params.framerate >> 16) + 1); +- +- /* Save stream headers */ +- buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +- switch (dst_fourcc) { +- case V4L2_PIX_FMT_H264: +- /* +- * Get SPS in the first frame and copy it to an +- * intermediate buffer. +- */ +- ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS, +- &ctx->vpu_header[0][0], +- &ctx->vpu_header_size[0]); +- if (ret < 0) +- goto out; +- +- /* +- * If visible width or height are not aligned to macroblock +- * size, the crop_right and crop_bottom SPS fields must be set +- * to the difference between visible and coded size. This is +- * only supported by CODA960 firmware. All others do not allow +- * writing frame cropping parameters, so we have to manually +- * fix up the SPS RBSP (Sequence Parameter Set Raw Byte +- * Sequence Payload) ourselves. +- */ +- if (ctx->dev->devtype->product != CODA_960 && +- ((q_data_src->rect.width % 16) || +- (q_data_src->rect.height % 16))) { +- ret = coda_h264_sps_fixup(ctx, q_data_src->rect.width, +- q_data_src->rect.height, +- &ctx->vpu_header[0][0], +- &ctx->vpu_header_size[0], +- sizeof(ctx->vpu_header[0])); +- if (ret < 0) +- goto out; +- } +- +- /* +- * Get PPS in the first frame and copy it to an +- * intermediate buffer. +- */ +- ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS, +- &ctx->vpu_header[1][0], +- &ctx->vpu_header_size[1]); +- if (ret < 0) +- goto out; +- +- /* +- * Length of H.264 headers is variable and thus it might not be +- * aligned for the coda to append the encoded frame. In that is +- * the case a filler NAL must be added to header 2. +- */ +- ctx->vpu_header_size[2] = coda_h264_padding( +- (ctx->vpu_header_size[0] + +- ctx->vpu_header_size[1]), +- ctx->vpu_header[2]); +- break; +- case V4L2_PIX_FMT_MPEG4: +- /* +- * Get VOS in the first frame and copy it to an +- * intermediate buffer +- */ +- ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS, +- &ctx->vpu_header[0][0], +- &ctx->vpu_header_size[0]); +- if (ret < 0) +- goto out; +- +- ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS, +- &ctx->vpu_header[1][0], +- &ctx->vpu_header_size[1]); +- if (ret < 0) +- goto out; +- +- ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL, +- &ctx->vpu_header[2][0], +- &ctx->vpu_header_size[2]); +- if (ret < 0) +- goto out; +- break; +- default: +- /* No more formats need to save headers at the moment */ +- break; +- } +- +-out: +- mutex_unlock(&dev->coda_mutex); +- return ret; +-} +- +-static int coda_prepare_encode(struct coda_ctx *ctx) +-{ +- struct coda_q_data *q_data_src, *q_data_dst; +- struct vb2_v4l2_buffer *src_buf, *dst_buf; +- struct coda_dev *dev = ctx->dev; +- int force_ipicture; +- int quant_param = 0; +- u32 pic_stream_buffer_addr, pic_stream_buffer_size; +- u32 rot_mode = 0; +- u32 dst_fourcc; +- u32 reg; +- int ret; +- +- ret = coda_enc_param_change(ctx); +- if (ret < 0) { +- v4l2_warn(&ctx->dev->v4l2_dev, "parameter change failed: %d\n", +- ret); +- } +- +- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); +- dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- dst_fourcc = q_data_dst->fourcc; +- +- src_buf->sequence = ctx->osequence; +- dst_buf->sequence = ctx->osequence; +- ctx->osequence++; +- +- force_ipicture = ctx->params.force_ipicture; +- if (force_ipicture) +- ctx->params.force_ipicture = false; +- else if (ctx->params.gop_size != 0 && +- (src_buf->sequence % ctx->params.gop_size) == 0) +- force_ipicture = 1; +- +- /* +- * Workaround coda firmware BUG that only marks the first +- * frame as IDR. This is a problem for some decoders that can't +- * recover when a frame is lost. +- */ +- if (!force_ipicture) { +- src_buf->flags |= V4L2_BUF_FLAG_PFRAME; +- src_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME; +- } else { +- src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; +- src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME; +- } +- +- if (dev->devtype->product == CODA_960) +- coda_set_gdi_regs(ctx); +- +- /* +- * Copy headers in front of the first frame and forced I frames for +- * H.264 only. In MPEG4 they are already copied by the CODA. +- */ +- if (src_buf->sequence == 0 || force_ipicture) { +- pic_stream_buffer_addr = +- vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0) + +- ctx->vpu_header_size[0] + +- ctx->vpu_header_size[1] + +- ctx->vpu_header_size[2]; +- pic_stream_buffer_size = q_data_dst->sizeimage - +- ctx->vpu_header_size[0] - +- ctx->vpu_header_size[1] - +- ctx->vpu_header_size[2]; +- memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0), +- &ctx->vpu_header[0][0], ctx->vpu_header_size[0]); +- memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) +- + ctx->vpu_header_size[0], &ctx->vpu_header[1][0], +- ctx->vpu_header_size[1]); +- memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0) +- + ctx->vpu_header_size[0] + ctx->vpu_header_size[1], +- &ctx->vpu_header[2][0], ctx->vpu_header_size[2]); +- } else { +- pic_stream_buffer_addr = +- vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); +- pic_stream_buffer_size = q_data_dst->sizeimage; +- } +- +- if (force_ipicture) { +- switch (dst_fourcc) { +- case V4L2_PIX_FMT_H264: +- quant_param = ctx->params.h264_intra_qp; +- break; +- case V4L2_PIX_FMT_MPEG4: +- quant_param = ctx->params.mpeg4_intra_qp; +- break; +- case V4L2_PIX_FMT_JPEG: +- quant_param = 30; +- break; +- default: +- v4l2_warn(&ctx->dev->v4l2_dev, +- "cannot set intra qp, fmt not supported\n"); +- break; +- } +- } else { +- switch (dst_fourcc) { +- case V4L2_PIX_FMT_H264: +- quant_param = ctx->params.h264_inter_qp; +- break; +- case V4L2_PIX_FMT_MPEG4: +- quant_param = ctx->params.mpeg4_inter_qp; +- break; +- default: +- v4l2_warn(&ctx->dev->v4l2_dev, +- "cannot set inter qp, fmt not supported\n"); +- break; +- } +- } +- +- /* submit */ +- if (ctx->params.rot_mode) +- rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode; +- coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE); +- coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS); +- +- if (dev->devtype->product == CODA_960) { +- coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX); +- coda_write(dev, q_data_src->bytesperline, +- CODA9_CMD_ENC_PIC_SRC_STRIDE); +- coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC); +- +- reg = CODA9_CMD_ENC_PIC_SRC_ADDR_Y; +- } else { +- reg = CODA_CMD_ENC_PIC_SRC_ADDR_Y; +- } +- coda_write_base(ctx, q_data_src, src_buf, reg); +- +- coda_write(dev, force_ipicture << 1 & 0x2, +- CODA_CMD_ENC_PIC_OPTION); +- +- coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START); +- coda_write(dev, pic_stream_buffer_size / 1024, +- CODA_CMD_ENC_PIC_BB_SIZE); +- +- if (!ctx->streamon_out) { +- /* After streamoff on the output side, set stream end flag */ +- ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; +- coda_write(dev, ctx->bit_stream_param, +- CODA_REG_BIT_BIT_STREAM_PARAM); +- } +- +- if (dev->devtype->product != CODA_DX6) +- coda_write(dev, ctx->iram_info.axi_sram_use, +- CODA7_REG_BIT_AXI_SRAM_USE); +- +- trace_coda_enc_pic_run(ctx, src_buf); +- +- coda_command_async(ctx, CODA_COMMAND_PIC_RUN); +- +- return 0; +-} +- +-static char coda_frame_type_char(u32 flags) +-{ +- return (flags & V4L2_BUF_FLAG_KEYFRAME) ? 'I' : +- (flags & V4L2_BUF_FLAG_PFRAME) ? 'P' : +- (flags & V4L2_BUF_FLAG_BFRAME) ? 'B' : '?'; +-} +- +-static void coda_finish_encode(struct coda_ctx *ctx) +-{ +- struct vb2_v4l2_buffer *src_buf, *dst_buf; +- struct coda_dev *dev = ctx->dev; +- u32 wr_ptr, start_ptr; +- +- if (ctx->aborting) +- return; +- +- /* +- * Lock to make sure that an encoder stop command running in parallel +- * will either already have marked src_buf as last, or it will wake up +- * the capture queue after the buffers are returned. +- */ +- mutex_lock(&ctx->wakeup_mutex); +- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); +- dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +- +- trace_coda_enc_pic_done(ctx, dst_buf); +- +- /* Get results from the coda */ +- start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START); +- wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)); +- +- /* Calculate bytesused field */ +- if (dst_buf->sequence == 0 || +- src_buf->flags & V4L2_BUF_FLAG_KEYFRAME) { +- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr + +- ctx->vpu_header_size[0] + +- ctx->vpu_header_size[1] + +- ctx->vpu_header_size[2]); +- } else { +- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr); +- } +- +- coda_dbg(1, ctx, "frame size = %u\n", wr_ptr - start_ptr); +- +- coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM); +- coda_read(dev, CODA_RET_ENC_PIC_FLAG); +- +- dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | +- V4L2_BUF_FLAG_PFRAME | +- V4L2_BUF_FLAG_LAST); +- if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0) +- dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; +- else +- dst_buf->flags |= V4L2_BUF_FLAG_PFRAME; +- dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST; +- +- v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); +- +- v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); +- +- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); +- coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE); +- mutex_unlock(&ctx->wakeup_mutex); +- +- ctx->gopcounter--; +- if (ctx->gopcounter < 0) +- ctx->gopcounter = ctx->params.gop_size - 1; +- +- coda_dbg(1, ctx, "job finished: encoded %c frame (%d)%s\n", +- coda_frame_type_char(dst_buf->flags), dst_buf->sequence, +- (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : ""); +-} +- +-static void coda_seq_end_work(struct work_struct *work) +-{ +- struct coda_ctx *ctx = container_of(work, struct coda_ctx, seq_end_work); +- struct coda_dev *dev = ctx->dev; +- +- mutex_lock(&ctx->buffer_mutex); +- mutex_lock(&dev->coda_mutex); +- +- if (ctx->initialized == 0) +- goto out; +- +- coda_dbg(1, ctx, "%s: sent command 'SEQ_END' to coda\n", __func__); +- if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) { +- v4l2_err(&dev->v4l2_dev, +- "CODA_COMMAND_SEQ_END failed\n"); +- } +- +- /* +- * FIXME: Sometimes h.264 encoding fails with 8-byte sequences missing +- * from the output stream after the h.264 decoder has run. Resetting the +- * hardware after the decoder has finished seems to help. +- */ +- if (dev->devtype->product == CODA_960) +- coda_hw_reset(ctx); +- +- kfifo_init(&ctx->bitstream_fifo, +- ctx->bitstream.vaddr, ctx->bitstream.size); +- +- coda_free_framebuffers(ctx); +- +- ctx->initialized = 0; +- +-out: +- mutex_unlock(&dev->coda_mutex); +- mutex_unlock(&ctx->buffer_mutex); +-} +- +-static void coda_bit_release(struct coda_ctx *ctx) +-{ +- mutex_lock(&ctx->buffer_mutex); +- coda_free_framebuffers(ctx); +- coda_free_context_buffers(ctx); +- coda_free_bitstream_buffer(ctx); +- mutex_unlock(&ctx->buffer_mutex); +-} +- +-const struct coda_context_ops coda_bit_encode_ops = { +- .queue_init = coda_encoder_queue_init, +- .reqbufs = coda_encoder_reqbufs, +- .start_streaming = coda_start_encoding, +- .prepare_run = coda_prepare_encode, +- .finish_run = coda_finish_encode, +- .seq_end_work = coda_seq_end_work, +- .release = coda_bit_release, +-}; +- +-/* +- * Decoder context operations +- */ +- +-static int coda_alloc_bitstream_buffer(struct coda_ctx *ctx, +- struct coda_q_data *q_data) +-{ +- if (ctx->bitstream.vaddr) +- return 0; +- +- ctx->bitstream.size = roundup_pow_of_two(q_data->sizeimage * 2); +- ctx->bitstream.vaddr = dma_alloc_wc(ctx->dev->dev, ctx->bitstream.size, +- &ctx->bitstream.paddr, GFP_KERNEL); +- if (!ctx->bitstream.vaddr) { +- v4l2_err(&ctx->dev->v4l2_dev, +- "failed to allocate bitstream ringbuffer"); +- return -ENOMEM; +- } +- kfifo_init(&ctx->bitstream_fifo, +- ctx->bitstream.vaddr, ctx->bitstream.size); +- +- return 0; +-} +- +-static void coda_free_bitstream_buffer(struct coda_ctx *ctx) +-{ +- if (ctx->bitstream.vaddr == NULL) +- return; +- +- dma_free_wc(ctx->dev->dev, ctx->bitstream.size, ctx->bitstream.vaddr, +- ctx->bitstream.paddr); +- ctx->bitstream.vaddr = NULL; +- kfifo_init(&ctx->bitstream_fifo, NULL, 0); +-} +- +-static int coda_decoder_reqbufs(struct coda_ctx *ctx, +- struct v4l2_requestbuffers *rb) +-{ +- struct coda_q_data *q_data_src; +- int ret; +- +- if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) +- return 0; +- +- if (rb->count) { +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- ret = coda_alloc_context_buffers(ctx, q_data_src); +- if (ret < 0) +- return ret; +- ret = coda_alloc_bitstream_buffer(ctx, q_data_src); +- if (ret < 0) { +- coda_free_context_buffers(ctx); +- return ret; +- } +- } else { +- coda_free_bitstream_buffer(ctx); +- coda_free_context_buffers(ctx); +- } +- +- return 0; +-} +- +-static bool coda_reorder_enable(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- int profile; +- +- if (dev->devtype->product != CODA_HX4 && +- dev->devtype->product != CODA_7541 && +- dev->devtype->product != CODA_960) +- return false; +- +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) +- return false; +- +- if (ctx->codec->src_fourcc != V4L2_PIX_FMT_H264) +- return true; +- +- profile = coda_h264_profile(ctx->params.h264_profile_idc); +- if (profile < 0) +- v4l2_warn(&dev->v4l2_dev, "Unknown H264 Profile: %u\n", +- ctx->params.h264_profile_idc); +- +- /* Baseline profile does not support reordering */ +- return profile > V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; +-} +- +-static void coda_decoder_drop_used_metas(struct coda_ctx *ctx) +-{ +- struct coda_buffer_meta *meta, *tmp; +- +- /* +- * All metas that end at or before the RD pointer (fifo out), +- * are now consumed by the VPU and should be released. +- */ +- spin_lock(&ctx->buffer_meta_lock); +- list_for_each_entry_safe(meta, tmp, &ctx->buffer_meta_list, list) { +- if (ctx->bitstream_fifo.kfifo.out >= meta->end) { +- coda_dbg(2, ctx, "releasing meta: seq=%d start=%d end=%d\n", +- meta->sequence, meta->start, meta->end); +- +- list_del(&meta->list); +- ctx->num_metas--; +- ctx->first_frame_sequence++; +- kfree(meta); +- } +- } +- spin_unlock(&ctx->buffer_meta_lock); +-} +- +-static int __coda_decoder_seq_init(struct coda_ctx *ctx) +-{ +- struct coda_q_data *q_data_src, *q_data_dst; +- u32 bitstream_buf, bitstream_size; +- struct coda_dev *dev = ctx->dev; +- int width, height; +- u32 src_fourcc, dst_fourcc; +- u32 val; +- int ret; +- +- lockdep_assert_held(&dev->coda_mutex); +- +- coda_dbg(1, ctx, "Video Data Order Adapter: %s\n", +- ctx->use_vdoa ? "Enabled" : "Disabled"); +- +- /* Start decoding */ +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- bitstream_buf = ctx->bitstream.paddr; +- bitstream_size = ctx->bitstream.size; +- src_fourcc = q_data_src->fourcc; +- dst_fourcc = q_data_dst->fourcc; +- +- /* Update coda bitstream read and write pointers from kfifo */ +- coda_kfifo_sync_to_device_full(ctx); +- +- ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) | +- CODA9_FRAME_TILED2LINEAR); +- if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV) +- ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE; +- if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) +- ctx->frame_mem_ctrl |= (0x3 << 9) | +- ((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR); +- coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL); +- +- ctx->display_idx = -1; +- ctx->frm_dis_flg = 0; +- coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); +- +- coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START); +- coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE); +- val = 0; +- if (coda_reorder_enable(ctx)) +- val |= CODA_REORDER_ENABLE; +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) +- val |= CODA_NO_INT_ENABLE; +- coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION); +- +- ctx->params.codec_mode = ctx->codec->mode; +- if (dev->devtype->product == CODA_960 && +- src_fourcc == V4L2_PIX_FMT_MPEG4) +- ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4; +- else +- ctx->params.codec_mode_aux = 0; +- if (src_fourcc == V4L2_PIX_FMT_MPEG4) { +- coda_write(dev, CODA_MP4_CLASS_MPEG4, +- CODA_CMD_DEC_SEQ_MP4_ASP_CLASS); +- } +- if (src_fourcc == V4L2_PIX_FMT_H264) { +- if (dev->devtype->product == CODA_HX4 || +- dev->devtype->product == CODA_7541) { +- coda_write(dev, ctx->psbuf.paddr, +- CODA_CMD_DEC_SEQ_PS_BB_START); +- coda_write(dev, (CODA7_PS_BUF_SIZE / 1024), +- CODA_CMD_DEC_SEQ_PS_BB_SIZE); +- } +- if (dev->devtype->product == CODA_960) { +- coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN); +- coda_write(dev, 512, CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE); +- } +- } +- if (src_fourcc == V4L2_PIX_FMT_JPEG) +- coda_write(dev, 0, CODA_CMD_DEC_SEQ_JPG_THUMB_EN); +- if (dev->devtype->product != CODA_960) +- coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE); +- +- ctx->bit_stream_param = CODA_BIT_DEC_SEQ_INIT_ESCAPE; +- ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT); +- ctx->bit_stream_param = 0; +- if (ret) { +- v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n"); +- return ret; +- } +- ctx->sequence_offset = ~0U; +- ctx->initialized = 1; +- ctx->first_frame_sequence = 0; +- +- /* Update kfifo out pointer from coda bitstream read pointer */ +- coda_kfifo_sync_from_device(ctx); +- +- /* +- * After updating the read pointer, we need to check if +- * any metas are consumed and should be released. +- */ +- coda_decoder_drop_used_metas(ctx); +- +- if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) { +- v4l2_err(&dev->v4l2_dev, +- "CODA_COMMAND_SEQ_INIT failed, error code = 0x%x\n", +- coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON)); +- return -EAGAIN; +- } +- +- val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE); +- if (dev->devtype->product == CODA_DX6) { +- width = (val >> CODADX6_PICWIDTH_OFFSET) & CODADX6_PICWIDTH_MASK; +- height = val & CODADX6_PICHEIGHT_MASK; +- } else { +- width = (val >> CODA7_PICWIDTH_OFFSET) & CODA7_PICWIDTH_MASK; +- height = val & CODA7_PICHEIGHT_MASK; +- } +- +- if (width > q_data_dst->bytesperline || height > q_data_dst->height) { +- v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n", +- width, height, q_data_dst->bytesperline, +- q_data_dst->height); +- return -EINVAL; +- } +- +- width = round_up(width, 16); +- height = round_up(height, 16); +- +- coda_dbg(1, ctx, "start decoding: %dx%d\n", width, height); +- +- ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED); +- /* +- * If the VDOA is used, the decoder needs one additional frame, +- * because the frames are freed when the next frame is decoded. +- * Otherwise there are visible errors in the decoded frames (green +- * regions in displayed frames) and a broken order of frames (earlier +- * frames are sporadically displayed after later frames). +- */ +- if (ctx->use_vdoa) +- ctx->num_internal_frames += 1; +- if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) { +- v4l2_err(&dev->v4l2_dev, +- "not enough framebuffers to decode (%d < %d)\n", +- CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames); +- return -EINVAL; +- } +- +- if (src_fourcc == V4L2_PIX_FMT_H264) { +- u32 left_right; +- u32 top_bottom; +- +- left_right = coda_read(dev, CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT); +- top_bottom = coda_read(dev, CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM); +- +- q_data_dst->rect.left = (left_right >> 10) & 0x3ff; +- q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff; +- q_data_dst->rect.width = width - q_data_dst->rect.left - +- (left_right & 0x3ff); +- q_data_dst->rect.height = height - q_data_dst->rect.top - +- (top_bottom & 0x3ff); +- } +- +- if (dev->devtype->product != CODA_DX6) { +- u8 profile, level; +- +- val = coda_read(dev, CODA7_RET_DEC_SEQ_HEADER_REPORT); +- profile = val & 0xff; +- level = (val >> 8) & 0x7f; +- +- if (profile || level) +- coda_update_profile_level_ctrls(ctx, profile, level); +- } +- +- return 0; +-} +- +-static void coda_dec_seq_init_work(struct work_struct *work) +-{ +- struct coda_ctx *ctx = container_of(work, +- struct coda_ctx, seq_init_work); +- struct coda_dev *dev = ctx->dev; +- +- mutex_lock(&ctx->buffer_mutex); +- mutex_lock(&dev->coda_mutex); +- +- if (!ctx->initialized) +- __coda_decoder_seq_init(ctx); +- +- mutex_unlock(&dev->coda_mutex); +- mutex_unlock(&ctx->buffer_mutex); +-} +- +-static int __coda_start_decoding(struct coda_ctx *ctx) +-{ +- struct coda_q_data *q_data_src, *q_data_dst; +- struct coda_dev *dev = ctx->dev; +- u32 src_fourcc, dst_fourcc; +- int ret; +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- src_fourcc = q_data_src->fourcc; +- dst_fourcc = q_data_dst->fourcc; +- +- if (!ctx->initialized) { +- ret = __coda_decoder_seq_init(ctx); +- if (ret < 0) +- return ret; +- } else { +- ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) | +- CODA9_FRAME_TILED2LINEAR); +- if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV) +- ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE; +- if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) +- ctx->frame_mem_ctrl |= (0x3 << 9) | +- ((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR); +- } +- +- coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR); +- +- ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc); +- if (ret < 0) { +- v4l2_err(&dev->v4l2_dev, "failed to allocate framebuffers\n"); +- return ret; +- } +- +- /* Tell the decoder how many frame buffers we allocated. */ +- coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM); +- coda_write(dev, round_up(q_data_dst->rect.width, 16), +- CODA_CMD_SET_FRAME_BUF_STRIDE); +- +- if (dev->devtype->product != CODA_DX6) { +- /* Set secondary AXI IRAM */ +- coda_setup_iram(ctx); +- +- coda_write(dev, ctx->iram_info.buf_bit_use, +- CODA7_CMD_SET_FRAME_AXI_BIT_ADDR); +- coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use, +- CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR); +- coda_write(dev, ctx->iram_info.buf_dbk_y_use, +- CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR); +- coda_write(dev, ctx->iram_info.buf_dbk_c_use, +- CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR); +- coda_write(dev, ctx->iram_info.buf_ovl_use, +- CODA7_CMD_SET_FRAME_AXI_OVL_ADDR); +- if (dev->devtype->product == CODA_960) { +- coda_write(dev, ctx->iram_info.buf_btp_use, +- CODA9_CMD_SET_FRAME_AXI_BTP_ADDR); +- +- coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY); +- coda9_set_frame_cache(ctx, dst_fourcc); +- } +- } +- +- if (src_fourcc == V4L2_PIX_FMT_H264) { +- coda_write(dev, ctx->slicebuf.paddr, +- CODA_CMD_SET_FRAME_SLICE_BB_START); +- coda_write(dev, ctx->slicebuf.size / 1024, +- CODA_CMD_SET_FRAME_SLICE_BB_SIZE); +- } +- +- if (dev->devtype->product == CODA_HX4 || +- dev->devtype->product == CODA_7541) { +- int max_mb_x = 1920 / 16; +- int max_mb_y = 1088 / 16; +- int max_mb_num = max_mb_x * max_mb_y; +- +- coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, +- CODA7_CMD_SET_FRAME_MAX_DEC_SIZE); +- } else if (dev->devtype->product == CODA_960) { +- int max_mb_x = 1920 / 16; +- int max_mb_y = 1088 / 16; +- int max_mb_num = max_mb_x * max_mb_y; +- +- coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y, +- CODA9_CMD_SET_FRAME_MAX_DEC_SIZE); +- } +- +- if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) { +- v4l2_err(&ctx->dev->v4l2_dev, +- "CODA_COMMAND_SET_FRAME_BUF timeout\n"); +- return -ETIMEDOUT; +- } +- +- return 0; +-} +- +-static int coda_start_decoding(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- int ret; +- +- mutex_lock(&dev->coda_mutex); +- ret = __coda_start_decoding(ctx); +- mutex_unlock(&dev->coda_mutex); +- +- return ret; +-} +- +-static int coda_prepare_decode(struct coda_ctx *ctx) +-{ +- struct vb2_v4l2_buffer *dst_buf; +- struct coda_dev *dev = ctx->dev; +- struct coda_q_data *q_data_dst; +- struct coda_buffer_meta *meta; +- u32 rot_mode = 0; +- u32 reg_addr, reg_stride; +- +- dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- +- /* Try to copy source buffer contents into the bitstream ringbuffer */ +- mutex_lock(&ctx->bitstream_mutex); +- coda_fill_bitstream(ctx, NULL); +- mutex_unlock(&ctx->bitstream_mutex); +- +- if (coda_get_bitstream_payload(ctx) < 512 && +- (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) { +- coda_dbg(1, ctx, "bitstream payload: %d, skipping\n", +- coda_get_bitstream_payload(ctx)); +- return -EAGAIN; +- } +- +- /* Run coda_start_decoding (again) if not yet initialized */ +- if (!ctx->initialized) { +- int ret = __coda_start_decoding(ctx); +- +- if (ret < 0) { +- v4l2_err(&dev->v4l2_dev, "failed to start decoding\n"); +- return -EAGAIN; +- } else { +- ctx->initialized = 1; +- } +- } +- +- if (dev->devtype->product == CODA_960) +- coda_set_gdi_regs(ctx); +- +- if (ctx->use_vdoa && +- ctx->display_idx >= 0 && +- ctx->display_idx < ctx->num_internal_frames) { +- vdoa_device_run(ctx->vdoa, +- vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0), +- ctx->internal_frames[ctx->display_idx].buf.paddr); +- } else { +- if (dev->devtype->product == CODA_960) { +- /* +- * It was previously assumed that the CODA960 has an +- * internal list of 64 buffer entries that contains +- * both the registered internal frame buffers as well +- * as the rotator buffer output, and that the ROT_INDEX +- * register must be set to a value between the last +- * internal frame buffers' index and 64. +- * At least on firmware version 3.1.1 it turns out that +- * setting ROT_INDEX to any value >= 32 causes CODA +- * hangups that it can not recover from with the SRC VPU +- * reset. +- * It does appear to work however, to just set it to a +- * fixed value in the [ctx->num_internal_frames, 31] +- * range, for example CODA_MAX_FRAMEBUFFERS. +- */ +- coda_write(dev, CODA_MAX_FRAMEBUFFERS, +- CODA9_CMD_DEC_PIC_ROT_INDEX); +- +- reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y; +- reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE; +- } else { +- reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y; +- reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE; +- } +- coda_write_base(ctx, q_data_dst, dst_buf, reg_addr); +- coda_write(dev, q_data_dst->bytesperline, reg_stride); +- +- rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode; +- } +- +- coda_write(dev, rot_mode, CODA_CMD_DEC_PIC_ROT_MODE); +- +- switch (dev->devtype->product) { +- case CODA_DX6: +- /* TBD */ +- case CODA_HX4: +- case CODA_7541: +- coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION); +- break; +- case CODA_960: +- /* 'hardcode to use interrupt disable mode'? */ +- coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION); +- break; +- } +- +- coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM); +- +- coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START); +- coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE); +- +- if (dev->devtype->product != CODA_DX6) +- coda_write(dev, ctx->iram_info.axi_sram_use, +- CODA7_REG_BIT_AXI_SRAM_USE); +- +- spin_lock(&ctx->buffer_meta_lock); +- meta = list_first_entry_or_null(&ctx->buffer_meta_list, +- struct coda_buffer_meta, list); +- +- if (meta && ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) { +- +- /* If this is the last buffer in the bitstream, add padding */ +- if (meta->end == ctx->bitstream_fifo.kfifo.in) { +- static unsigned char buf[512]; +- unsigned int pad; +- +- /* Pad to multiple of 256 and then add 256 more */ +- pad = ((0 - meta->end) & 0xff) + 256; +- +- memset(buf, 0xff, sizeof(buf)); +- +- kfifo_in(&ctx->bitstream_fifo, buf, pad); +- } +- } +- spin_unlock(&ctx->buffer_meta_lock); +- +- coda_kfifo_sync_to_device_full(ctx); +- +- /* Clear decode success flag */ +- coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS); +- +- /* Clear error return value */ +- coda_write(dev, 0, CODA_RET_DEC_PIC_ERR_MB); +- +- trace_coda_dec_pic_run(ctx, meta); +- +- coda_command_async(ctx, CODA_COMMAND_PIC_RUN); +- +- return 0; +-} +- +-static void coda_finish_decode(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- struct coda_q_data *q_data_src; +- struct coda_q_data *q_data_dst; +- struct vb2_v4l2_buffer *dst_buf; +- struct coda_buffer_meta *meta; +- int width, height; +- int decoded_idx; +- int display_idx; +- struct coda_internal_frame *decoded_frame = NULL; +- u32 src_fourcc; +- int success; +- u32 err_mb; +- int err_vdoa = 0; +- u32 val; +- +- if (ctx->aborting) +- return; +- +- /* Update kfifo out pointer from coda bitstream read pointer */ +- coda_kfifo_sync_from_device(ctx); +- +- /* +- * in stream-end mode, the read pointer can overshoot the write pointer +- * by up to 512 bytes +- */ +- if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) { +- if (coda_get_bitstream_payload(ctx) >= ctx->bitstream.size - 512) +- kfifo_init(&ctx->bitstream_fifo, +- ctx->bitstream.vaddr, ctx->bitstream.size); +- } +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- src_fourcc = q_data_src->fourcc; +- +- val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS); +- if (val != 1) +- pr_err("DEC_PIC_SUCCESS = %d\n", val); +- +- success = val & 0x1; +- if (!success) +- v4l2_err(&dev->v4l2_dev, "decode failed\n"); +- +- if (src_fourcc == V4L2_PIX_FMT_H264) { +- if (val & (1 << 3)) +- v4l2_err(&dev->v4l2_dev, +- "insufficient PS buffer space (%d bytes)\n", +- ctx->psbuf.size); +- if (val & (1 << 2)) +- v4l2_err(&dev->v4l2_dev, +- "insufficient slice buffer space (%d bytes)\n", +- ctx->slicebuf.size); +- } +- +- val = coda_read(dev, CODA_RET_DEC_PIC_SIZE); +- width = (val >> 16) & 0xffff; +- height = val & 0xffff; +- +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- +- /* frame crop information */ +- if (src_fourcc == V4L2_PIX_FMT_H264) { +- u32 left_right; +- u32 top_bottom; +- +- left_right = coda_read(dev, CODA_RET_DEC_PIC_CROP_LEFT_RIGHT); +- top_bottom = coda_read(dev, CODA_RET_DEC_PIC_CROP_TOP_BOTTOM); +- +- if (left_right == 0xffffffff && top_bottom == 0xffffffff) { +- /* Keep current crop information */ +- } else { +- struct v4l2_rect *rect = &q_data_dst->rect; +- +- rect->left = left_right >> 16 & 0xffff; +- rect->top = top_bottom >> 16 & 0xffff; +- rect->width = width - rect->left - +- (left_right & 0xffff); +- rect->height = height - rect->top - +- (top_bottom & 0xffff); +- } +- } else { +- /* no cropping */ +- } +- +- err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB); +- if (err_mb > 0) { +- if (__ratelimit(&dev->mb_err_rs)) +- coda_dbg(1, ctx, "errors in %d macroblocks\n", err_mb); +- v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, +- v4l2_ctrl_g_ctrl(ctx->mb_err_cnt_ctrl) + err_mb); +- } +- +- if (dev->devtype->product == CODA_HX4 || +- dev->devtype->product == CODA_7541) { +- val = coda_read(dev, CODA_RET_DEC_PIC_OPTION); +- if (val == 0) { +- /* not enough bitstream data */ +- coda_dbg(1, ctx, "prescan failed: %d\n", val); +- ctx->hold = true; +- return; +- } +- } +- +- /* Wait until the VDOA finished writing the previous display frame */ +- if (ctx->use_vdoa && +- ctx->display_idx >= 0 && +- ctx->display_idx < ctx->num_internal_frames) { +- err_vdoa = vdoa_wait_for_completion(ctx->vdoa); +- } +- +- ctx->frm_dis_flg = coda_read(dev, +- CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); +- +- /* The previous display frame was copied out and can be overwritten */ +- if (ctx->display_idx >= 0 && +- ctx->display_idx < ctx->num_internal_frames) { +- ctx->frm_dis_flg &= ~(1 << ctx->display_idx); +- coda_write(dev, ctx->frm_dis_flg, +- CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx)); +- } +- +- /* +- * The index of the last decoded frame, not necessarily in +- * display order, and the index of the next display frame. +- * The latter could have been decoded in a previous run. +- */ +- decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX); +- display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX); +- +- if (decoded_idx == -1) { +- /* no frame was decoded, but we might have a display frame */ +- if (display_idx >= 0 && display_idx < ctx->num_internal_frames) +- ctx->sequence_offset++; +- else if (ctx->display_idx < 0) +- ctx->hold = true; +- } else if (decoded_idx == -2) { +- if (ctx->display_idx >= 0 && +- ctx->display_idx < ctx->num_internal_frames) +- ctx->sequence_offset++; +- /* no frame was decoded, we still return remaining buffers */ +- } else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) { +- v4l2_err(&dev->v4l2_dev, +- "decoded frame index out of range: %d\n", decoded_idx); +- } else { +- int sequence; +- +- decoded_frame = &ctx->internal_frames[decoded_idx]; +- +- val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM); +- if (ctx->sequence_offset == -1) +- ctx->sequence_offset = val; +- +- sequence = val + ctx->first_frame_sequence +- - ctx->sequence_offset; +- spin_lock(&ctx->buffer_meta_lock); +- if (!list_empty(&ctx->buffer_meta_list)) { +- meta = list_first_entry(&ctx->buffer_meta_list, +- struct coda_buffer_meta, list); +- list_del(&meta->list); +- ctx->num_metas--; +- spin_unlock(&ctx->buffer_meta_lock); +- /* +- * Clamp counters to 16 bits for comparison, as the HW +- * counter rolls over at this point for h.264. This +- * may be different for other formats, but using 16 bits +- * should be enough to detect most errors and saves us +- * from doing different things based on the format. +- */ +- if ((sequence & 0xffff) != (meta->sequence & 0xffff)) { +- v4l2_err(&dev->v4l2_dev, +- "sequence number mismatch (%d(%d) != %d)\n", +- sequence, ctx->sequence_offset, +- meta->sequence); +- } +- decoded_frame->meta = *meta; +- kfree(meta); +- } else { +- spin_unlock(&ctx->buffer_meta_lock); +- v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n"); +- memset(&decoded_frame->meta, 0, +- sizeof(struct coda_buffer_meta)); +- decoded_frame->meta.sequence = sequence; +- decoded_frame->meta.last = false; +- ctx->sequence_offset++; +- } +- +- trace_coda_dec_pic_done(ctx, &decoded_frame->meta); +- +- val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7; +- decoded_frame->type = (val == 0) ? V4L2_BUF_FLAG_KEYFRAME : +- (val == 1) ? V4L2_BUF_FLAG_PFRAME : +- V4L2_BUF_FLAG_BFRAME; +- +- decoded_frame->error = err_mb; +- } +- +- if (display_idx == -1) { +- /* +- * no more frames to be decoded, but there could still +- * be rotator output to dequeue +- */ +- ctx->hold = true; +- } else if (display_idx == -3) { +- /* possibly prescan failure */ +- } else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) { +- v4l2_err(&dev->v4l2_dev, +- "presentation frame index out of range: %d\n", +- display_idx); +- } +- +- /* If a frame was copied out, return it */ +- if (ctx->display_idx >= 0 && +- ctx->display_idx < ctx->num_internal_frames) { +- struct coda_internal_frame *ready_frame; +- +- ready_frame = &ctx->internal_frames[ctx->display_idx]; +- +- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); +- dst_buf->sequence = ctx->osequence++; +- +- dst_buf->field = V4L2_FIELD_NONE; +- dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME | +- V4L2_BUF_FLAG_PFRAME | +- V4L2_BUF_FLAG_BFRAME); +- dst_buf->flags |= ready_frame->type; +- meta = &ready_frame->meta; +- if (meta->last && !coda_reorder_enable(ctx)) { +- /* +- * If this was the last decoded frame, and reordering +- * is disabled, this will be the last display frame. +- */ +- coda_dbg(1, ctx, "last meta, marking as last frame\n"); +- dst_buf->flags |= V4L2_BUF_FLAG_LAST; +- } else if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG && +- display_idx == -1) { +- /* +- * If there is no designated presentation frame anymore, +- * this frame has to be the last one. +- */ +- coda_dbg(1, ctx, +- "no more frames to return, marking as last frame\n"); +- dst_buf->flags |= V4L2_BUF_FLAG_LAST; +- } +- dst_buf->timecode = meta->timecode; +- dst_buf->vb2_buf.timestamp = meta->timestamp; +- +- trace_coda_dec_rot_done(ctx, dst_buf, meta); +- +- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, +- q_data_dst->sizeimage); +- +- if (ready_frame->error || err_vdoa) +- coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR); +- else +- coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE); +- +- if (decoded_frame) { +- coda_dbg(1, ctx, "job finished: decoded %c frame %u, returned %c frame %u (%u/%u)%s\n", +- coda_frame_type_char(decoded_frame->type), +- decoded_frame->meta.sequence, +- coda_frame_type_char(dst_buf->flags), +- ready_frame->meta.sequence, +- dst_buf->sequence, ctx->qsequence, +- (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? +- " (last)" : ""); +- } else { +- coda_dbg(1, ctx, "job finished: no frame decoded (%d), returned %c frame %u (%u/%u)%s\n", +- decoded_idx, +- coda_frame_type_char(dst_buf->flags), +- ready_frame->meta.sequence, +- dst_buf->sequence, ctx->qsequence, +- (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? +- " (last)" : ""); +- } +- } else { +- if (decoded_frame) { +- coda_dbg(1, ctx, "job finished: decoded %c frame %u, no frame returned (%d)\n", +- coda_frame_type_char(decoded_frame->type), +- decoded_frame->meta.sequence, +- ctx->display_idx); +- } else { +- coda_dbg(1, ctx, "job finished: no frame decoded (%d) or returned (%d)\n", +- decoded_idx, ctx->display_idx); +- } +- } +- +- /* The rotator will copy the current display frame next time */ +- ctx->display_idx = display_idx; +- +- /* +- * The current decode run might have brought the bitstream fill level +- * below the size where we can start the next decode run. As userspace +- * might have filled the output queue completely and might thus be +- * blocked, we can't rely on the next qbuf to trigger the bitstream +- * refill. Check if we have data to refill the bitstream now. +- */ +- mutex_lock(&ctx->bitstream_mutex); +- coda_fill_bitstream(ctx, NULL); +- mutex_unlock(&ctx->bitstream_mutex); +-} +- +-static void coda_decode_timeout(struct coda_ctx *ctx) +-{ +- struct vb2_v4l2_buffer *dst_buf; +- +- /* +- * For now this only handles the case where we would deadlock with +- * userspace, i.e. userspace issued DEC_CMD_STOP and waits for EOS, +- * but after a failed decode run we would hold the context and wait for +- * userspace to queue more buffers. +- */ +- if (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)) +- return; +- +- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); +- dst_buf->sequence = ctx->qsequence - 1; +- +- coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR); +-} +- +-const struct coda_context_ops coda_bit_decode_ops = { +- .queue_init = coda_decoder_queue_init, +- .reqbufs = coda_decoder_reqbufs, +- .start_streaming = coda_start_decoding, +- .prepare_run = coda_prepare_decode, +- .finish_run = coda_finish_decode, +- .run_timeout = coda_decode_timeout, +- .seq_init_work = coda_dec_seq_init_work, +- .seq_end_work = coda_seq_end_work, +- .release = coda_bit_release, +-}; +- +-irqreturn_t coda_irq_handler(int irq, void *data) +-{ +- struct coda_dev *dev = data; +- struct coda_ctx *ctx; +- +- /* read status register to attend the IRQ */ +- coda_read(dev, CODA_REG_BIT_INT_STATUS); +- coda_write(dev, 0, CODA_REG_BIT_INT_REASON); +- coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET, +- CODA_REG_BIT_INT_CLEAR); +- +- ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); +- if (ctx == NULL) { +- v4l2_err(&dev->v4l2_dev, +- "Instance released before the end of transaction\n"); +- return IRQ_HANDLED; +- } +- +- trace_coda_bit_done(ctx); +- +- if (ctx->aborting) { +- coda_dbg(1, ctx, "task has been aborted\n"); +- } +- +- if (coda_isbusy(ctx->dev)) { +- coda_dbg(1, ctx, "coda is still busy!!!!\n"); +- return IRQ_NONE; +- } +- +- complete(&ctx->completion); +- +- return IRQ_HANDLED; +-} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-common.c b/drivers/media/platform/chips-media/coda-common.c +--- a/drivers/media/platform/chips-media/coda-common.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda-common.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,3361 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Coda multi-standard codec IP +- * +- * Copyright (C) 2012 Vista Silicon S.L. +- * Javier Martin, +- * Xavier Duret +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "coda.h" +-#include "imx-vdoa.h" +- +-#define CODA_NAME "coda" +- +-#define CODADX6_MAX_INSTANCES 4 +-#define CODA_MAX_FORMATS 5 +- +-#define CODA_ISRAM_SIZE (2048 * 2) +- +-#define MIN_W 48 +-#define MIN_H 16 +- +-#define S_ALIGN 1 /* multiple of 2 */ +-#define W_ALIGN 1 /* multiple of 2 */ +-#define H_ALIGN 1 /* multiple of 2 */ +- +-#define fh_to_ctx(__fh) container_of(__fh, struct coda_ctx, fh) +- +-int coda_debug; +-module_param(coda_debug, int, 0644); +-MODULE_PARM_DESC(coda_debug, "Debug level (0-2)"); +- +-static int disable_tiling; +-module_param(disable_tiling, int, 0644); +-MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers"); +- +-static int disable_vdoa; +-module_param(disable_vdoa, int, 0644); +-MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster-scan conversion"); +- +-static int enable_bwb = 0; +-module_param(enable_bwb, int, 0644); +-MODULE_PARM_DESC(enable_bwb, "Enable BWB unit for decoding, may crash on certain streams"); +- +-void coda_write(struct coda_dev *dev, u32 data, u32 reg) +-{ +- v4l2_dbg(3, coda_debug, &dev->v4l2_dev, +- "%s: data=0x%x, reg=0x%x\n", __func__, data, reg); +- writel(data, dev->regs_base + reg); +-} +- +-unsigned int coda_read(struct coda_dev *dev, u32 reg) +-{ +- u32 data; +- +- data = readl(dev->regs_base + reg); +- v4l2_dbg(3, coda_debug, &dev->v4l2_dev, +- "%s: data=0x%x, reg=0x%x\n", __func__, data, reg); +- return data; +-} +- +-void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data, +- struct vb2_v4l2_buffer *buf, unsigned int reg_y) +-{ +- u32 base_y = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0); +- u32 base_cb, base_cr; +- +- switch (q_data->fourcc) { +- case V4L2_PIX_FMT_YUYV: +- /* Fallthrough: IN -H264-> CODA -NV12 MB-> VDOA -YUYV-> OUT */ +- case V4L2_PIX_FMT_NV12: +- case V4L2_PIX_FMT_YUV420: +- default: +- base_cb = base_y + q_data->bytesperline * q_data->height; +- base_cr = base_cb + q_data->bytesperline * q_data->height / 4; +- break; +- case V4L2_PIX_FMT_YVU420: +- /* Switch Cb and Cr for YVU420 format */ +- base_cr = base_y + q_data->bytesperline * q_data->height; +- base_cb = base_cr + q_data->bytesperline * q_data->height / 4; +- break; +- case V4L2_PIX_FMT_YUV422P: +- base_cb = base_y + q_data->bytesperline * q_data->height; +- base_cr = base_cb + q_data->bytesperline * q_data->height / 2; +- } +- +- coda_write(ctx->dev, base_y, reg_y); +- coda_write(ctx->dev, base_cb, reg_y + 4); +- coda_write(ctx->dev, base_cr, reg_y + 8); +-} +- +-#define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \ +- { mode, src_fourcc, dst_fourcc, max_w, max_h } +- +-/* +- * Arrays of codecs supported by each given version of Coda: +- * i.MX27 -> codadx6 +- * i.MX51 -> codahx4 +- * i.MX53 -> coda7 +- * i.MX6 -> coda960 +- * Use V4L2_PIX_FMT_YUV420 as placeholder for all supported YUV 4:2:0 variants +- */ +-static const struct coda_codec codadx6_codecs[] = { +- CODA_CODEC(CODADX6_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 720, 576), +- CODA_CODEC(CODADX6_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 720, 576), +-}; +- +-static const struct coda_codec codahx4_codecs[] = { +- CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 720, 576), +- CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), +- CODA_CODEC(CODA7_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), +- CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1280, 720), +-}; +- +-static const struct coda_codec coda7_codecs[] = { +- CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720), +- CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720), +- CODA_CODEC(CODA7_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG, 8192, 8192), +- CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), +- CODA_CODEC(CODA7_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), +- CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), +- CODA_CODEC(CODA7_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420, 8192, 8192), +-}; +- +-static const struct coda_codec coda9_codecs[] = { +- CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1920, 1088), +- CODA_CODEC(CODA9_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1920, 1088), +- CODA_CODEC(CODA9_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG, 8192, 8192), +- CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088), +- CODA_CODEC(CODA9_MODE_DECODE_MP2, V4L2_PIX_FMT_MPEG2, V4L2_PIX_FMT_YUV420, 1920, 1088), +- CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088), +- CODA_CODEC(CODA9_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420, 8192, 8192), +-}; +- +-struct coda_video_device { +- const char *name; +- enum coda_inst_type type; +- const struct coda_context_ops *ops; +- bool direct; +- u32 src_formats[CODA_MAX_FORMATS]; +- u32 dst_formats[CODA_MAX_FORMATS]; +-}; +- +-static const struct coda_video_device coda_bit_encoder = { +- .name = "coda-video-encoder", +- .type = CODA_INST_ENCODER, +- .ops = &coda_bit_encode_ops, +- .src_formats = { +- V4L2_PIX_FMT_NV12, +- V4L2_PIX_FMT_YUV420, +- V4L2_PIX_FMT_YVU420, +- }, +- .dst_formats = { +- V4L2_PIX_FMT_H264, +- V4L2_PIX_FMT_MPEG4, +- }, +-}; +- +-static const struct coda_video_device coda_bit_jpeg_encoder = { +- .name = "coda-jpeg-encoder", +- .type = CODA_INST_ENCODER, +- .ops = &coda_bit_encode_ops, +- .src_formats = { +- V4L2_PIX_FMT_NV12, +- V4L2_PIX_FMT_YUV420, +- V4L2_PIX_FMT_YVU420, +- V4L2_PIX_FMT_YUV422P, +- }, +- .dst_formats = { +- V4L2_PIX_FMT_JPEG, +- }, +-}; +- +-static const struct coda_video_device coda_bit_decoder = { +- .name = "coda-video-decoder", +- .type = CODA_INST_DECODER, +- .ops = &coda_bit_decode_ops, +- .src_formats = { +- V4L2_PIX_FMT_H264, +- V4L2_PIX_FMT_MPEG2, +- V4L2_PIX_FMT_MPEG4, +- }, +- .dst_formats = { +- V4L2_PIX_FMT_NV12, +- V4L2_PIX_FMT_YUV420, +- V4L2_PIX_FMT_YVU420, +- /* +- * If V4L2_PIX_FMT_YUYV should be default, +- * set_default_params() must be adjusted. +- */ +- V4L2_PIX_FMT_YUYV, +- }, +-}; +- +-static const struct coda_video_device coda_bit_jpeg_decoder = { +- .name = "coda-jpeg-decoder", +- .type = CODA_INST_DECODER, +- .ops = &coda_bit_decode_ops, +- .src_formats = { +- V4L2_PIX_FMT_JPEG, +- }, +- .dst_formats = { +- V4L2_PIX_FMT_NV12, +- V4L2_PIX_FMT_YUV420, +- V4L2_PIX_FMT_YVU420, +- V4L2_PIX_FMT_YUV422P, +- }, +-}; +- +-static const struct coda_video_device coda9_jpeg_encoder = { +- .name = "coda-jpeg-encoder", +- .type = CODA_INST_ENCODER, +- .ops = &coda9_jpeg_encode_ops, +- .direct = true, +- .src_formats = { +- V4L2_PIX_FMT_NV12, +- V4L2_PIX_FMT_YUV420, +- V4L2_PIX_FMT_YVU420, +- V4L2_PIX_FMT_YUV422P, +- V4L2_PIX_FMT_GREY, +- }, +- .dst_formats = { +- V4L2_PIX_FMT_JPEG, +- }, +-}; +- +-static const struct coda_video_device coda9_jpeg_decoder = { +- .name = "coda-jpeg-decoder", +- .type = CODA_INST_DECODER, +- .ops = &coda9_jpeg_decode_ops, +- .direct = true, +- .src_formats = { +- V4L2_PIX_FMT_JPEG, +- }, +- .dst_formats = { +- V4L2_PIX_FMT_NV12, +- V4L2_PIX_FMT_YUV420, +- V4L2_PIX_FMT_YVU420, +- V4L2_PIX_FMT_YUV422P, +- }, +-}; +- +-static const struct coda_video_device *codadx6_video_devices[] = { +- &coda_bit_encoder, +-}; +- +-static const struct coda_video_device *codahx4_video_devices[] = { +- &coda_bit_encoder, +- &coda_bit_decoder, +-}; +- +-static const struct coda_video_device *coda7_video_devices[] = { +- &coda_bit_jpeg_encoder, +- &coda_bit_jpeg_decoder, +- &coda_bit_encoder, +- &coda_bit_decoder, +-}; +- +-static const struct coda_video_device *coda9_video_devices[] = { +- &coda9_jpeg_encoder, +- &coda9_jpeg_decoder, +- &coda_bit_encoder, +- &coda_bit_decoder, +-}; +- +-/* +- * Normalize all supported YUV 4:2:0 formats to the value used in the codec +- * tables. +- */ +-static u32 coda_format_normalize_yuv(u32 fourcc) +-{ +- switch (fourcc) { +- case V4L2_PIX_FMT_NV12: +- case V4L2_PIX_FMT_YUV420: +- case V4L2_PIX_FMT_YVU420: +- case V4L2_PIX_FMT_YUV422P: +- case V4L2_PIX_FMT_YUYV: +- return V4L2_PIX_FMT_YUV420; +- default: +- return fourcc; +- } +-} +- +-static const struct coda_codec *coda_find_codec(struct coda_dev *dev, +- int src_fourcc, int dst_fourcc) +-{ +- const struct coda_codec *codecs = dev->devtype->codecs; +- int num_codecs = dev->devtype->num_codecs; +- int k; +- +- src_fourcc = coda_format_normalize_yuv(src_fourcc); +- dst_fourcc = coda_format_normalize_yuv(dst_fourcc); +- if (src_fourcc == dst_fourcc) +- return NULL; +- +- for (k = 0; k < num_codecs; k++) { +- if (codecs[k].src_fourcc == src_fourcc && +- codecs[k].dst_fourcc == dst_fourcc) +- break; +- } +- +- if (k == num_codecs) +- return NULL; +- +- return &codecs[k]; +-} +- +-static void coda_get_max_dimensions(struct coda_dev *dev, +- const struct coda_codec *codec, +- int *max_w, int *max_h) +-{ +- const struct coda_codec *codecs = dev->devtype->codecs; +- int num_codecs = dev->devtype->num_codecs; +- unsigned int w, h; +- int k; +- +- if (codec) { +- w = codec->max_w; +- h = codec->max_h; +- } else { +- for (k = 0, w = 0, h = 0; k < num_codecs; k++) { +- w = max(w, codecs[k].max_w); +- h = max(h, codecs[k].max_h); +- } +- } +- +- if (max_w) +- *max_w = w; +- if (max_h) +- *max_h = h; +-} +- +-static const struct coda_video_device *to_coda_video_device(struct video_device +- *vdev) +-{ +- struct coda_dev *dev = video_get_drvdata(vdev); +- unsigned int i = vdev - dev->vfd; +- +- if (i >= dev->devtype->num_vdevs) +- return NULL; +- +- return dev->devtype->vdevs[i]; +-} +- +-const char *coda_product_name(int product) +-{ +- static char buf[9]; +- +- switch (product) { +- case CODA_DX6: +- return "CodaDx6"; +- case CODA_HX4: +- return "CodaHx4"; +- case CODA_7541: +- return "CODA7541"; +- case CODA_960: +- return "CODA960"; +- default: +- snprintf(buf, sizeof(buf), "(0x%04x)", product); +- return buf; +- } +-} +- +-static struct vdoa_data *coda_get_vdoa_data(void) +-{ +- struct device_node *vdoa_node; +- struct platform_device *vdoa_pdev; +- struct vdoa_data *vdoa_data = NULL; +- +- vdoa_node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-vdoa"); +- if (!vdoa_node) +- return NULL; +- +- vdoa_pdev = of_find_device_by_node(vdoa_node); +- if (!vdoa_pdev) +- goto out; +- +- vdoa_data = platform_get_drvdata(vdoa_pdev); +- if (!vdoa_data) +- vdoa_data = ERR_PTR(-EPROBE_DEFER); +- +- put_device(&vdoa_pdev->dev); +-out: +- of_node_put(vdoa_node); +- +- return vdoa_data; +-} +- +-/* +- * V4L2 ioctl() operations. +- */ +-static int coda_querycap(struct file *file, void *priv, +- struct v4l2_capability *cap) +-{ +- struct coda_ctx *ctx = fh_to_ctx(priv); +- +- strscpy(cap->driver, CODA_NAME, sizeof(cap->driver)); +- strscpy(cap->card, coda_product_name(ctx->dev->devtype->product), +- sizeof(cap->card)); +- strscpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info)); +- return 0; +-} +- +-static const u32 coda_formats_420[CODA_MAX_FORMATS] = { +- V4L2_PIX_FMT_NV12, +- V4L2_PIX_FMT_YUV420, +- V4L2_PIX_FMT_YVU420, +-}; +- +-static int coda_enum_fmt(struct file *file, void *priv, +- struct v4l2_fmtdesc *f) +-{ +- struct video_device *vdev = video_devdata(file); +- const struct coda_video_device *cvd = to_coda_video_device(vdev); +- struct coda_ctx *ctx = fh_to_ctx(priv); +- const u32 *formats; +- +- if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) +- formats = cvd->src_formats; +- else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { +- struct coda_q_data *q_data_src; +- struct vb2_queue *src_vq; +- +- formats = cvd->dst_formats; +- +- /* +- * If the source format is already fixed, only allow the same +- * chroma subsampling. +- */ +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, +- V4L2_BUF_TYPE_VIDEO_OUTPUT); +- if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG && +- vb2_is_streaming(src_vq)) { +- if (ctx->params.jpeg_chroma_subsampling == +- V4L2_JPEG_CHROMA_SUBSAMPLING_420) { +- formats = coda_formats_420; +- } else if (ctx->params.jpeg_chroma_subsampling == +- V4L2_JPEG_CHROMA_SUBSAMPLING_422) { +- f->pixelformat = V4L2_PIX_FMT_YUV422P; +- return f->index ? -EINVAL : 0; +- } +- } +- } else { +- return -EINVAL; +- } +- +- if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0) +- return -EINVAL; +- +- /* Skip YUYV if the vdoa is not available */ +- if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && +- formats[f->index] == V4L2_PIX_FMT_YUYV) +- return -EINVAL; +- +- f->pixelformat = formats[f->index]; +- +- return 0; +-} +- +-static int coda_g_fmt(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct coda_q_data *q_data; +- struct coda_ctx *ctx = fh_to_ctx(priv); +- +- q_data = get_q_data(ctx, f->type); +- if (!q_data) +- return -EINVAL; +- +- f->fmt.pix.field = V4L2_FIELD_NONE; +- f->fmt.pix.pixelformat = q_data->fourcc; +- f->fmt.pix.width = q_data->width; +- f->fmt.pix.height = q_data->height; +- f->fmt.pix.bytesperline = q_data->bytesperline; +- +- f->fmt.pix.sizeimage = q_data->sizeimage; +- f->fmt.pix.colorspace = ctx->colorspace; +- f->fmt.pix.xfer_func = ctx->xfer_func; +- f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; +- f->fmt.pix.quantization = ctx->quantization; +- +- return 0; +-} +- +-static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f) +-{ +- struct coda_q_data *q_data; +- const u32 *formats; +- int i; +- +- if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) +- formats = ctx->cvd->src_formats; +- else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) +- formats = ctx->cvd->dst_formats; +- else +- return -EINVAL; +- +- for (i = 0; i < CODA_MAX_FORMATS; i++) { +- /* Skip YUYV if the vdoa is not available */ +- if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && +- formats[i] == V4L2_PIX_FMT_YUYV) +- continue; +- +- if (formats[i] == f->fmt.pix.pixelformat) { +- f->fmt.pix.pixelformat = formats[i]; +- return 0; +- } +- } +- +- /* Fall back to currently set pixelformat */ +- q_data = get_q_data(ctx, f->type); +- f->fmt.pix.pixelformat = q_data->fourcc; +- +- return 0; +-} +- +-static int coda_try_fmt_vdoa(struct coda_ctx *ctx, struct v4l2_format *f, +- bool *use_vdoa) +-{ +- int err; +- +- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) +- return -EINVAL; +- +- if (!use_vdoa) +- return -EINVAL; +- +- if (!ctx->vdoa) { +- *use_vdoa = false; +- return 0; +- } +- +- err = vdoa_context_configure(NULL, round_up(f->fmt.pix.width, 16), +- f->fmt.pix.height, f->fmt.pix.pixelformat); +- if (err) { +- *use_vdoa = false; +- return 0; +- } +- +- *use_vdoa = true; +- return 0; +-} +- +-static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage, +- u32 width, u32 height) +-{ +- /* +- * This is a rough estimate for sensible compressed buffer +- * sizes (between 1 and 16 bits per pixel). This could be +- * improved by better format specific worst case estimates. +- */ +- return round_up(clamp(sizeimage, width * height / 8, +- width * height * 2), PAGE_SIZE); +-} +- +-static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec, +- struct v4l2_format *f) +-{ +- struct coda_dev *dev = ctx->dev; +- unsigned int max_w, max_h; +- enum v4l2_field field; +- +- field = f->fmt.pix.field; +- if (field == V4L2_FIELD_ANY) +- field = V4L2_FIELD_NONE; +- else if (V4L2_FIELD_NONE != field) +- return -EINVAL; +- +- /* V4L2 specification suggests the driver corrects the format struct +- * if any of the dimensions is unsupported */ +- f->fmt.pix.field = field; +- +- coda_get_max_dimensions(dev, codec, &max_w, &max_h); +- v4l_bound_align_image(&f->fmt.pix.width, MIN_W, max_w, W_ALIGN, +- &f->fmt.pix.height, MIN_H, max_h, H_ALIGN, +- S_ALIGN); +- +- switch (f->fmt.pix.pixelformat) { +- case V4L2_PIX_FMT_NV12: +- case V4L2_PIX_FMT_YUV420: +- case V4L2_PIX_FMT_YVU420: +- /* +- * Frame stride must be at least multiple of 8, +- * but multiple of 16 for h.264 or JPEG 4:2:x +- */ +- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); +- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * +- f->fmt.pix.height * 3 / 2; +- break; +- case V4L2_PIX_FMT_YUYV: +- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2; +- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * +- f->fmt.pix.height; +- break; +- case V4L2_PIX_FMT_YUV422P: +- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); +- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * +- f->fmt.pix.height * 2; +- break; +- case V4L2_PIX_FMT_GREY: +- /* keep 16 pixel alignment of 8-bit pixel data */ +- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16); +- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height; +- break; +- case V4L2_PIX_FMT_JPEG: +- case V4L2_PIX_FMT_H264: +- case V4L2_PIX_FMT_MPEG4: +- case V4L2_PIX_FMT_MPEG2: +- f->fmt.pix.bytesperline = 0; +- f->fmt.pix.sizeimage = coda_estimate_sizeimage(ctx, +- f->fmt.pix.sizeimage, +- f->fmt.pix.width, +- f->fmt.pix.height); +- break; +- default: +- BUG(); +- } +- +- return 0; +-} +- +-static int coda_try_fmt_vid_cap(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct coda_ctx *ctx = fh_to_ctx(priv); +- const struct coda_q_data *q_data_src; +- const struct coda_codec *codec; +- struct vb2_queue *src_vq; +- int hscale = 0; +- int vscale = 0; +- int ret; +- bool use_vdoa; +- +- ret = coda_try_pixelformat(ctx, f); +- if (ret < 0) +- return ret; +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- +- /* +- * If the source format is already fixed, only allow the same output +- * resolution. When decoding JPEG images, we also have to make sure to +- * use the same chroma subsampling. +- */ +- src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- if (vb2_is_streaming(src_vq)) { +- if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG && +- ctx->dev->devtype->product == CODA_960) { +- hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width); +- vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height); +- } +- f->fmt.pix.width = q_data_src->width >> hscale; +- f->fmt.pix.height = q_data_src->height >> vscale; +- +- if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) { +- if (ctx->params.jpeg_chroma_subsampling == +- V4L2_JPEG_CHROMA_SUBSAMPLING_420 && +- f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) +- f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12; +- else if (ctx->params.jpeg_chroma_subsampling == +- V4L2_JPEG_CHROMA_SUBSAMPLING_422) +- f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P; +- } +- } +- +- f->fmt.pix.colorspace = ctx->colorspace; +- f->fmt.pix.xfer_func = ctx->xfer_func; +- f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc; +- f->fmt.pix.quantization = ctx->quantization; +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- codec = coda_find_codec(ctx->dev, q_data_src->fourcc, +- f->fmt.pix.pixelformat); +- if (!codec) +- return -EINVAL; +- +- ret = coda_try_fmt(ctx, codec, f); +- if (ret < 0) +- return ret; +- +- /* The decoders always write complete macroblocks or MCUs */ +- if (ctx->inst_type == CODA_INST_DECODER) { +- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16 >> hscale); +- f->fmt.pix.height = round_up(f->fmt.pix.height, 16 >> vscale); +- if (codec->src_fourcc == V4L2_PIX_FMT_JPEG && +- f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) { +- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * +- f->fmt.pix.height * 2; +- } else { +- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * +- f->fmt.pix.height * 3 / 2; +- } +- +- ret = coda_try_fmt_vdoa(ctx, f, &use_vdoa); +- if (ret < 0) +- return ret; +- +- if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) { +- if (!use_vdoa) +- return -EINVAL; +- +- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2; +- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * +- f->fmt.pix.height; +- } +- } +- +- return 0; +-} +- +-static void coda_set_default_colorspace(struct v4l2_pix_format *fmt) +-{ +- enum v4l2_colorspace colorspace; +- +- if (fmt->pixelformat == V4L2_PIX_FMT_JPEG) +- colorspace = V4L2_COLORSPACE_JPEG; +- else if (fmt->width <= 720 && fmt->height <= 576) +- colorspace = V4L2_COLORSPACE_SMPTE170M; +- else +- colorspace = V4L2_COLORSPACE_REC709; +- +- fmt->colorspace = colorspace; +- fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT; +- fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; +- fmt->quantization = V4L2_QUANTIZATION_DEFAULT; +-} +- +-static int coda_try_fmt_vid_out(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct coda_ctx *ctx = fh_to_ctx(priv); +- struct coda_dev *dev = ctx->dev; +- const struct coda_q_data *q_data_dst; +- const struct coda_codec *codec; +- int ret; +- +- ret = coda_try_pixelformat(ctx, f); +- if (ret < 0) +- return ret; +- +- if (f->fmt.pix.colorspace == V4L2_COLORSPACE_DEFAULT) +- coda_set_default_colorspace(&f->fmt.pix); +- +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc); +- +- return coda_try_fmt(ctx, codec, f); +-} +- +-static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f, +- struct v4l2_rect *r) +-{ +- struct coda_q_data *q_data; +- struct vb2_queue *vq; +- +- vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); +- if (!vq) +- return -EINVAL; +- +- q_data = get_q_data(ctx, f->type); +- if (!q_data) +- return -EINVAL; +- +- if (vb2_is_busy(vq)) { +- v4l2_err(&ctx->dev->v4l2_dev, "%s: %s queue busy: %d\n", +- __func__, v4l2_type_names[f->type], vq->num_buffers); +- return -EBUSY; +- } +- +- q_data->fourcc = f->fmt.pix.pixelformat; +- q_data->width = f->fmt.pix.width; +- q_data->height = f->fmt.pix.height; +- q_data->bytesperline = f->fmt.pix.bytesperline; +- q_data->sizeimage = f->fmt.pix.sizeimage; +- if (r) { +- q_data->rect = *r; +- } else { +- q_data->rect.left = 0; +- q_data->rect.top = 0; +- q_data->rect.width = f->fmt.pix.width; +- q_data->rect.height = f->fmt.pix.height; +- } +- +- switch (f->fmt.pix.pixelformat) { +- case V4L2_PIX_FMT_YUYV: +- ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP; +- break; +- case V4L2_PIX_FMT_NV12: +- if (!disable_tiling && ctx->use_bit && +- ctx->dev->devtype->product == CODA_960) { +- ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP; +- break; +- } +- fallthrough; +- case V4L2_PIX_FMT_YUV420: +- case V4L2_PIX_FMT_YVU420: +- case V4L2_PIX_FMT_YUV422P: +- ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP; +- break; +- default: +- break; +- } +- +- if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP && +- !coda_try_fmt_vdoa(ctx, f, &ctx->use_vdoa) && +- ctx->use_vdoa) +- vdoa_context_configure(ctx->vdoa, +- round_up(f->fmt.pix.width, 16), +- f->fmt.pix.height, +- f->fmt.pix.pixelformat); +- else +- ctx->use_vdoa = false; +- +- coda_dbg(1, ctx, "Setting %s format, wxh: %dx%d, fmt: %4.4s %c\n", +- v4l2_type_names[f->type], q_data->width, q_data->height, +- (char *)&q_data->fourcc, +- (ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) ? 'L' : 'T'); +- +- return 0; +-} +- +-static int coda_s_fmt_vid_cap(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct coda_ctx *ctx = fh_to_ctx(priv); +- struct coda_q_data *q_data_src; +- const struct coda_codec *codec; +- struct v4l2_rect r; +- int hscale = 0; +- int vscale = 0; +- int ret; +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- +- if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG && +- ctx->dev->devtype->product == CODA_960) { +- hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width); +- vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height); +- } +- +- ret = coda_try_fmt_vid_cap(file, priv, f); +- if (ret) +- return ret; +- +- r.left = 0; +- r.top = 0; +- r.width = q_data_src->width >> hscale; +- r.height = q_data_src->height >> vscale; +- +- ret = coda_s_fmt(ctx, f, &r); +- if (ret) +- return ret; +- +- if (ctx->inst_type != CODA_INST_ENCODER) +- return 0; +- +- /* Setting the coded format determines the selected codec */ +- codec = coda_find_codec(ctx->dev, q_data_src->fourcc, +- f->fmt.pix.pixelformat); +- if (!codec) { +- v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n"); +- return -EINVAL; +- } +- ctx->codec = codec; +- +- ctx->colorspace = f->fmt.pix.colorspace; +- ctx->xfer_func = f->fmt.pix.xfer_func; +- ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; +- ctx->quantization = f->fmt.pix.quantization; +- +- return 0; +-} +- +-static int coda_s_fmt_vid_out(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct coda_ctx *ctx = fh_to_ctx(priv); +- const struct coda_codec *codec; +- struct v4l2_format f_cap; +- struct vb2_queue *dst_vq; +- int ret; +- +- ret = coda_try_fmt_vid_out(file, priv, f); +- if (ret) +- return ret; +- +- ret = coda_s_fmt(ctx, f, NULL); +- if (ret) +- return ret; +- +- ctx->colorspace = f->fmt.pix.colorspace; +- ctx->xfer_func = f->fmt.pix.xfer_func; +- ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; +- ctx->quantization = f->fmt.pix.quantization; +- +- if (ctx->inst_type != CODA_INST_DECODER) +- return 0; +- +- /* Setting the coded format determines the selected codec */ +- codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat, +- V4L2_PIX_FMT_YUV420); +- if (!codec) { +- v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n"); +- return -EINVAL; +- } +- ctx->codec = codec; +- +- dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- if (!dst_vq) +- return -EINVAL; +- +- /* +- * Setting the capture queue format is not possible while the capture +- * queue is still busy. This is not an error, but the user will have to +- * make sure themselves that the capture format is set correctly before +- * starting the output queue again. +- */ +- if (vb2_is_busy(dst_vq)) +- return 0; +- +- memset(&f_cap, 0, sizeof(f_cap)); +- f_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +- coda_g_fmt(file, priv, &f_cap); +- f_cap.fmt.pix.width = f->fmt.pix.width; +- f_cap.fmt.pix.height = f->fmt.pix.height; +- +- return coda_s_fmt_vid_cap(file, priv, &f_cap); +-} +- +-static int coda_reqbufs(struct file *file, void *priv, +- struct v4l2_requestbuffers *rb) +-{ +- struct coda_ctx *ctx = fh_to_ctx(priv); +- int ret; +- +- ret = v4l2_m2m_reqbufs(file, ctx->fh.m2m_ctx, rb); +- if (ret) +- return ret; +- +- /* +- * Allow to allocate instance specific per-context buffers, such as +- * bitstream ringbuffer, slice buffer, work buffer, etc. if needed. +- */ +- if (rb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && ctx->ops->reqbufs) +- return ctx->ops->reqbufs(ctx, rb); +- +- return 0; +-} +- +-static int coda_qbuf(struct file *file, void *priv, +- struct v4l2_buffer *buf) +-{ +- struct coda_ctx *ctx = fh_to_ctx(priv); +- +- if (ctx->inst_type == CODA_INST_DECODER && +- buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) +- buf->flags &= ~V4L2_BUF_FLAG_LAST; +- +- return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf); +-} +- +-static int coda_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) +-{ +- struct coda_ctx *ctx = fh_to_ctx(priv); +- int ret; +- +- ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf); +- +- if (ctx->inst_type == CODA_INST_DECODER && +- buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) +- buf->flags &= ~V4L2_BUF_FLAG_LAST; +- +- return ret; +-} +- +-void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, +- enum vb2_buffer_state state) +-{ +- const struct v4l2_event eos_event = { +- .type = V4L2_EVENT_EOS +- }; +- +- if (buf->flags & V4L2_BUF_FLAG_LAST) +- v4l2_event_queue_fh(&ctx->fh, &eos_event); +- +- v4l2_m2m_buf_done(buf, state); +-} +- +-static int coda_g_selection(struct file *file, void *fh, +- struct v4l2_selection *s) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- struct coda_q_data *q_data; +- struct v4l2_rect r, *rsel; +- +- q_data = get_q_data(ctx, s->type); +- if (!q_data) +- return -EINVAL; +- +- r.left = 0; +- r.top = 0; +- r.width = q_data->width; +- r.height = q_data->height; +- rsel = &q_data->rect; +- +- switch (s->target) { +- case V4L2_SEL_TGT_CROP_DEFAULT: +- case V4L2_SEL_TGT_CROP_BOUNDS: +- rsel = &r; +- fallthrough; +- case V4L2_SEL_TGT_CROP: +- if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT || +- ctx->inst_type == CODA_INST_DECODER) +- return -EINVAL; +- break; +- case V4L2_SEL_TGT_COMPOSE_BOUNDS: +- case V4L2_SEL_TGT_COMPOSE_PADDED: +- rsel = &r; +- fallthrough; +- case V4L2_SEL_TGT_COMPOSE: +- case V4L2_SEL_TGT_COMPOSE_DEFAULT: +- if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || +- ctx->inst_type == CODA_INST_ENCODER) +- return -EINVAL; +- break; +- default: +- return -EINVAL; +- } +- +- s->r = *rsel; +- +- return 0; +-} +- +-static int coda_s_selection(struct file *file, void *fh, +- struct v4l2_selection *s) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- struct coda_q_data *q_data; +- +- switch (s->target) { +- case V4L2_SEL_TGT_CROP: +- if (ctx->inst_type == CODA_INST_ENCODER && +- s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { +- q_data = get_q_data(ctx, s->type); +- if (!q_data) +- return -EINVAL; +- +- s->r.left = 0; +- s->r.top = 0; +- s->r.width = clamp(s->r.width, 2U, q_data->width); +- s->r.height = clamp(s->r.height, 2U, q_data->height); +- +- if (s->flags & V4L2_SEL_FLAG_LE) { +- s->r.width = round_up(s->r.width, 2); +- s->r.height = round_up(s->r.height, 2); +- } else { +- s->r.width = round_down(s->r.width, 2); +- s->r.height = round_down(s->r.height, 2); +- } +- +- q_data->rect = s->r; +- +- coda_dbg(1, ctx, "Setting crop rectangle: %dx%d\n", +- s->r.width, s->r.height); +- +- return 0; +- } +- fallthrough; +- case V4L2_SEL_TGT_NATIVE_SIZE: +- case V4L2_SEL_TGT_COMPOSE: +- return coda_g_selection(file, fh, s); +- default: +- /* v4l2-compliance expects this to fail for read-only targets */ +- return -EINVAL; +- } +-} +- +-static void coda_wake_up_capture_queue(struct coda_ctx *ctx) +-{ +- struct vb2_queue *dst_vq; +- +- coda_dbg(1, ctx, "waking up capture queue\n"); +- +- dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- dst_vq->last_buffer_dequeued = true; +- wake_up(&dst_vq->done_wq); +-} +- +-static int coda_encoder_cmd(struct file *file, void *fh, +- struct v4l2_encoder_cmd *ec) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- struct vb2_v4l2_buffer *buf; +- int ret; +- +- ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec); +- if (ret < 0) +- return ret; +- +- mutex_lock(&ctx->wakeup_mutex); +- buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx); +- if (buf) { +- /* +- * If the last output buffer is still on the queue, make sure +- * that decoder finish_run will see the last flag and report it +- * to userspace. +- */ +- buf->flags |= V4L2_BUF_FLAG_LAST; +- } else { +- /* Set the stream-end flag on this context */ +- ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG; +- +- /* +- * If the last output buffer has already been taken from the +- * queue, wake up the capture queue and signal end of stream +- * via the -EPIPE mechanism. +- */ +- coda_wake_up_capture_queue(ctx); +- } +- mutex_unlock(&ctx->wakeup_mutex); +- +- return 0; +-} +- +-static bool coda_mark_last_meta(struct coda_ctx *ctx) +-{ +- struct coda_buffer_meta *meta; +- +- coda_dbg(1, ctx, "marking last meta\n"); +- +- spin_lock(&ctx->buffer_meta_lock); +- if (list_empty(&ctx->buffer_meta_list)) { +- spin_unlock(&ctx->buffer_meta_lock); +- return false; +- } +- +- meta = list_last_entry(&ctx->buffer_meta_list, struct coda_buffer_meta, +- list); +- meta->last = true; +- +- spin_unlock(&ctx->buffer_meta_lock); +- return true; +-} +- +-static bool coda_mark_last_dst_buf(struct coda_ctx *ctx) +-{ +- struct vb2_v4l2_buffer *buf; +- struct vb2_buffer *dst_vb; +- struct vb2_queue *dst_vq; +- unsigned long flags; +- +- coda_dbg(1, ctx, "marking last capture buffer\n"); +- +- dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- spin_lock_irqsave(&dst_vq->done_lock, flags); +- if (list_empty(&dst_vq->done_list)) { +- spin_unlock_irqrestore(&dst_vq->done_lock, flags); +- return false; +- } +- +- dst_vb = list_last_entry(&dst_vq->done_list, struct vb2_buffer, +- done_entry); +- buf = to_vb2_v4l2_buffer(dst_vb); +- buf->flags |= V4L2_BUF_FLAG_LAST; +- +- spin_unlock_irqrestore(&dst_vq->done_lock, flags); +- return true; +-} +- +-static int coda_decoder_cmd(struct file *file, void *fh, +- struct v4l2_decoder_cmd *dc) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- struct coda_dev *dev = ctx->dev; +- struct vb2_v4l2_buffer *buf; +- struct vb2_queue *dst_vq; +- bool stream_end; +- bool wakeup; +- int ret; +- +- ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc); +- if (ret < 0) +- return ret; +- +- switch (dc->cmd) { +- case V4L2_DEC_CMD_START: +- mutex_lock(&dev->coda_mutex); +- mutex_lock(&ctx->bitstream_mutex); +- coda_bitstream_flush(ctx); +- dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, +- V4L2_BUF_TYPE_VIDEO_CAPTURE); +- vb2_clear_last_buffer_dequeued(dst_vq); +- ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG; +- coda_fill_bitstream(ctx, NULL); +- mutex_unlock(&ctx->bitstream_mutex); +- mutex_unlock(&dev->coda_mutex); +- break; +- case V4L2_DEC_CMD_STOP: +- stream_end = false; +- wakeup = false; +- +- mutex_lock(&ctx->wakeup_mutex); +- +- buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx); +- if (buf) { +- coda_dbg(1, ctx, "marking last pending buffer\n"); +- +- /* Mark last buffer */ +- buf->flags |= V4L2_BUF_FLAG_LAST; +- +- if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0) { +- coda_dbg(1, ctx, "all remaining buffers queued\n"); +- stream_end = true; +- } +- } else { +- if (ctx->use_bit) +- if (coda_mark_last_meta(ctx)) +- stream_end = true; +- else +- wakeup = true; +- else +- if (!coda_mark_last_dst_buf(ctx)) +- wakeup = true; +- } +- +- if (stream_end) { +- coda_dbg(1, ctx, "all remaining buffers queued\n"); +- +- /* Set the stream-end flag on this context */ +- coda_bit_stream_end_flag(ctx); +- ctx->hold = false; +- v4l2_m2m_try_schedule(ctx->fh.m2m_ctx); +- } +- +- if (wakeup) { +- /* If there is no buffer in flight, wake up */ +- coda_wake_up_capture_queue(ctx); +- } +- +- mutex_unlock(&ctx->wakeup_mutex); +- break; +- default: +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int coda_enum_framesizes(struct file *file, void *fh, +- struct v4l2_frmsizeenum *fsize) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- struct coda_q_data *q_data_dst; +- const struct coda_codec *codec; +- +- if (fsize->index) +- return -EINVAL; +- +- if (coda_format_normalize_yuv(fsize->pixel_format) == +- V4L2_PIX_FMT_YUV420) { +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- codec = coda_find_codec(ctx->dev, fsize->pixel_format, +- q_data_dst->fourcc); +- } else { +- codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, +- fsize->pixel_format); +- } +- if (!codec) +- return -EINVAL; +- +- fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; +- fsize->stepwise.min_width = MIN_W; +- fsize->stepwise.max_width = codec->max_w; +- fsize->stepwise.step_width = 1; +- fsize->stepwise.min_height = MIN_H; +- fsize->stepwise.max_height = codec->max_h; +- fsize->stepwise.step_height = 1; +- +- return 0; +-} +- +-static int coda_enum_frameintervals(struct file *file, void *fh, +- struct v4l2_frmivalenum *f) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- struct coda_q_data *q_data; +- const struct coda_codec *codec; +- +- if (f->index) +- return -EINVAL; +- +- /* Disallow YUYV if the vdoa is not available */ +- if (!ctx->vdoa && f->pixel_format == V4L2_PIX_FMT_YUYV) +- return -EINVAL; +- +- if (coda_format_normalize_yuv(f->pixel_format) == V4L2_PIX_FMT_YUV420) { +- q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- codec = coda_find_codec(ctx->dev, f->pixel_format, +- q_data->fourcc); +- } else { +- codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420, +- f->pixel_format); +- } +- if (!codec) +- return -EINVAL; +- +- if (f->width < MIN_W || f->width > codec->max_w || +- f->height < MIN_H || f->height > codec->max_h) +- return -EINVAL; +- +- f->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; +- f->stepwise.min.numerator = 1; +- f->stepwise.min.denominator = 65535; +- f->stepwise.max.numerator = 65536; +- f->stepwise.max.denominator = 1; +- f->stepwise.step.numerator = 1; +- f->stepwise.step.denominator = 1; +- +- return 0; +-} +- +-static int coda_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- struct v4l2_fract *tpf; +- +- if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) +- return -EINVAL; +- +- a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; +- tpf = &a->parm.output.timeperframe; +- tpf->denominator = ctx->params.framerate & CODA_FRATE_RES_MASK; +- tpf->numerator = 1 + (ctx->params.framerate >> +- CODA_FRATE_DIV_OFFSET); +- +- return 0; +-} +- +-/* +- * Approximate timeperframe v4l2_fract with values that can be written +- * into the 16-bit CODA_FRATE_DIV and CODA_FRATE_RES fields. +- */ +-static void coda_approximate_timeperframe(struct v4l2_fract *timeperframe) +-{ +- struct v4l2_fract s = *timeperframe; +- struct v4l2_fract f0; +- struct v4l2_fract f1 = { 1, 0 }; +- struct v4l2_fract f2 = { 0, 1 }; +- unsigned int i, div, s_denominator; +- +- /* Lower bound is 1/65535 */ +- if (s.numerator == 0 || s.denominator / s.numerator > 65535) { +- timeperframe->numerator = 1; +- timeperframe->denominator = 65535; +- return; +- } +- +- /* Upper bound is 65536/1 */ +- if (s.denominator == 0 || s.numerator / s.denominator > 65536) { +- timeperframe->numerator = 65536; +- timeperframe->denominator = 1; +- return; +- } +- +- /* Reduce fraction to lowest terms */ +- div = gcd(s.numerator, s.denominator); +- if (div > 1) { +- s.numerator /= div; +- s.denominator /= div; +- } +- +- if (s.numerator <= 65536 && s.denominator < 65536) { +- *timeperframe = s; +- return; +- } +- +- /* Find successive convergents from continued fraction expansion */ +- while (f2.numerator <= 65536 && f2.denominator < 65536) { +- f0 = f1; +- f1 = f2; +- +- /* Stop when f2 exactly equals timeperframe */ +- if (s.numerator == 0) +- break; +- +- i = s.denominator / s.numerator; +- +- f2.numerator = f0.numerator + i * f1.numerator; +- f2.denominator = f0.denominator + i * f2.denominator; +- +- s_denominator = s.numerator; +- s.numerator = s.denominator % s.numerator; +- s.denominator = s_denominator; +- } +- +- *timeperframe = f1; +-} +- +-static uint32_t coda_timeperframe_to_frate(struct v4l2_fract *timeperframe) +-{ +- return ((timeperframe->numerator - 1) << CODA_FRATE_DIV_OFFSET) | +- timeperframe->denominator; +-} +- +-static int coda_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- struct v4l2_fract *tpf; +- +- if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) +- return -EINVAL; +- +- a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; +- tpf = &a->parm.output.timeperframe; +- coda_approximate_timeperframe(tpf); +- ctx->params.framerate = coda_timeperframe_to_frate(tpf); +- ctx->params.framerate_changed = true; +- +- return 0; +-} +- +-static int coda_subscribe_event(struct v4l2_fh *fh, +- const struct v4l2_event_subscription *sub) +-{ +- struct coda_ctx *ctx = fh_to_ctx(fh); +- +- switch (sub->type) { +- case V4L2_EVENT_EOS: +- return v4l2_event_subscribe(fh, sub, 0, NULL); +- case V4L2_EVENT_SOURCE_CHANGE: +- if (ctx->inst_type == CODA_INST_DECODER) +- return v4l2_event_subscribe(fh, sub, 0, NULL); +- else +- return -EINVAL; +- default: +- return v4l2_ctrl_subscribe_event(fh, sub); +- } +-} +- +-static const struct v4l2_ioctl_ops coda_ioctl_ops = { +- .vidioc_querycap = coda_querycap, +- +- .vidioc_enum_fmt_vid_cap = coda_enum_fmt, +- .vidioc_g_fmt_vid_cap = coda_g_fmt, +- .vidioc_try_fmt_vid_cap = coda_try_fmt_vid_cap, +- .vidioc_s_fmt_vid_cap = coda_s_fmt_vid_cap, +- +- .vidioc_enum_fmt_vid_out = coda_enum_fmt, +- .vidioc_g_fmt_vid_out = coda_g_fmt, +- .vidioc_try_fmt_vid_out = coda_try_fmt_vid_out, +- .vidioc_s_fmt_vid_out = coda_s_fmt_vid_out, +- +- .vidioc_reqbufs = coda_reqbufs, +- .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, +- +- .vidioc_qbuf = coda_qbuf, +- .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, +- .vidioc_dqbuf = coda_dqbuf, +- .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, +- .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, +- +- .vidioc_streamon = v4l2_m2m_ioctl_streamon, +- .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, +- +- .vidioc_g_selection = coda_g_selection, +- .vidioc_s_selection = coda_s_selection, +- +- .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, +- .vidioc_encoder_cmd = coda_encoder_cmd, +- .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, +- .vidioc_decoder_cmd = coda_decoder_cmd, +- +- .vidioc_g_parm = coda_g_parm, +- .vidioc_s_parm = coda_s_parm, +- +- .vidioc_enum_framesizes = coda_enum_framesizes, +- .vidioc_enum_frameintervals = coda_enum_frameintervals, +- +- .vidioc_subscribe_event = coda_subscribe_event, +- .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +-}; +- +-/* +- * Mem-to-mem operations. +- */ +- +-static void coda_device_run(void *m2m_priv) +-{ +- struct coda_ctx *ctx = m2m_priv; +- struct coda_dev *dev = ctx->dev; +- +- queue_work(dev->workqueue, &ctx->pic_run_work); +-} +- +-static void coda_pic_run_work(struct work_struct *work) +-{ +- struct coda_ctx *ctx = container_of(work, struct coda_ctx, pic_run_work); +- struct coda_dev *dev = ctx->dev; +- int ret; +- +- mutex_lock(&ctx->buffer_mutex); +- mutex_lock(&dev->coda_mutex); +- +- ret = ctx->ops->prepare_run(ctx); +- if (ret < 0 && ctx->inst_type == CODA_INST_DECODER) +- goto out; +- +- if (!wait_for_completion_timeout(&ctx->completion, +- msecs_to_jiffies(1000))) { +- if (ctx->use_bit) { +- dev_err(dev->dev, "CODA PIC_RUN timeout\n"); +- +- ctx->hold = true; +- +- coda_hw_reset(ctx); +- } +- +- if (ctx->ops->run_timeout) +- ctx->ops->run_timeout(ctx); +- } else { +- ctx->ops->finish_run(ctx); +- } +- +- if ((ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) && +- ctx->ops->seq_end_work) +- queue_work(dev->workqueue, &ctx->seq_end_work); +- +-out: +- mutex_unlock(&dev->coda_mutex); +- mutex_unlock(&ctx->buffer_mutex); +- +- v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx); +-} +- +-static int coda_job_ready(void *m2m_priv) +-{ +- struct coda_ctx *ctx = m2m_priv; +- int src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx); +- +- /* +- * For both 'P' and 'key' frame cases 1 picture +- * and 1 frame are needed. In the decoder case, +- * the compressed frame can be in the bitstream. +- */ +- if (!src_bufs && ctx->inst_type != CODA_INST_DECODER) { +- coda_dbg(1, ctx, "not ready: not enough vid-out buffers.\n"); +- return 0; +- } +- +- if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) { +- coda_dbg(1, ctx, "not ready: not enough vid-cap buffers.\n"); +- return 0; +- } +- +- if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) { +- bool stream_end = ctx->bit_stream_param & +- CODA_BIT_STREAM_END_FLAG; +- int num_metas = ctx->num_metas; +- struct coda_buffer_meta *meta; +- unsigned int count; +- +- count = hweight32(ctx->frm_dis_flg); +- if (ctx->use_vdoa && count >= (ctx->num_internal_frames - 1)) { +- coda_dbg(1, ctx, +- "not ready: all internal buffers in use: %d/%d (0x%x)", +- count, ctx->num_internal_frames, +- ctx->frm_dis_flg); +- return 0; +- } +- +- if (ctx->hold && !src_bufs) { +- coda_dbg(1, ctx, +- "not ready: on hold for more buffers.\n"); +- return 0; +- } +- +- if (!stream_end && (num_metas + src_bufs) < 2) { +- coda_dbg(1, ctx, +- "not ready: need 2 buffers available (queue:%d + bitstream:%d)\n", +- num_metas, src_bufs); +- return 0; +- } +- +- meta = list_first_entry(&ctx->buffer_meta_list, +- struct coda_buffer_meta, list); +- if (!coda_bitstream_can_fetch_past(ctx, meta->end) && +- !stream_end) { +- coda_dbg(1, ctx, +- "not ready: not enough bitstream data to read past %u (%u)\n", +- meta->end, ctx->bitstream_fifo.kfifo.in); +- return 0; +- } +- } +- +- if (ctx->aborting) { +- coda_dbg(1, ctx, "not ready: aborting\n"); +- return 0; +- } +- +- coda_dbg(2, ctx, "job ready\n"); +- +- return 1; +-} +- +-static void coda_job_abort(void *priv) +-{ +- struct coda_ctx *ctx = priv; +- +- ctx->aborting = 1; +- +- coda_dbg(1, ctx, "job abort\n"); +-} +- +-static const struct v4l2_m2m_ops coda_m2m_ops = { +- .device_run = coda_device_run, +- .job_ready = coda_job_ready, +- .job_abort = coda_job_abort, +-}; +- +-static void set_default_params(struct coda_ctx *ctx) +-{ +- unsigned int max_w, max_h, usize, csize; +- +- ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0], +- ctx->cvd->dst_formats[0]); +- max_w = min(ctx->codec->max_w, 1920U); +- max_h = min(ctx->codec->max_h, 1088U); +- usize = max_w * max_h * 3 / 2; +- csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h); +- +- ctx->params.codec_mode = ctx->codec->mode; +- if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_JPEG || +- ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG) { +- ctx->colorspace = V4L2_COLORSPACE_SRGB; +- ctx->xfer_func = V4L2_XFER_FUNC_SRGB; +- ctx->ycbcr_enc = V4L2_YCBCR_ENC_601; +- ctx->quantization = V4L2_QUANTIZATION_FULL_RANGE; +- } else { +- ctx->colorspace = V4L2_COLORSPACE_REC709; +- ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT; +- ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; +- ctx->quantization = V4L2_QUANTIZATION_DEFAULT; +- } +- ctx->params.framerate = 30; +- +- /* Default formats for output and input queues */ +- ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->cvd->src_formats[0]; +- ctx->q_data[V4L2_M2M_DST].fourcc = ctx->cvd->dst_formats[0]; +- ctx->q_data[V4L2_M2M_SRC].width = max_w; +- ctx->q_data[V4L2_M2M_SRC].height = max_h; +- ctx->q_data[V4L2_M2M_DST].width = max_w; +- ctx->q_data[V4L2_M2M_DST].height = max_h; +- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) { +- ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w; +- ctx->q_data[V4L2_M2M_SRC].sizeimage = usize; +- ctx->q_data[V4L2_M2M_DST].bytesperline = 0; +- ctx->q_data[V4L2_M2M_DST].sizeimage = csize; +- } else { +- ctx->q_data[V4L2_M2M_SRC].bytesperline = 0; +- ctx->q_data[V4L2_M2M_SRC].sizeimage = csize; +- ctx->q_data[V4L2_M2M_DST].bytesperline = max_w; +- ctx->q_data[V4L2_M2M_DST].sizeimage = usize; +- } +- ctx->q_data[V4L2_M2M_SRC].rect.width = max_w; +- ctx->q_data[V4L2_M2M_SRC].rect.height = max_h; +- ctx->q_data[V4L2_M2M_DST].rect.width = max_w; +- ctx->q_data[V4L2_M2M_DST].rect.height = max_h; +- +- /* +- * Since the RBC2AXI logic only supports a single chroma plane, +- * macroblock tiling only works for to NV12 pixel format. +- */ +- ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP; +-} +- +-/* +- * Queue operations +- */ +-static int coda_queue_setup(struct vb2_queue *vq, +- unsigned int *nbuffers, unsigned int *nplanes, +- unsigned int sizes[], struct device *alloc_devs[]) +-{ +- struct coda_ctx *ctx = vb2_get_drv_priv(vq); +- struct coda_q_data *q_data; +- unsigned int size; +- +- q_data = get_q_data(ctx, vq->type); +- size = q_data->sizeimage; +- +- if (*nplanes) +- return sizes[0] < size ? -EINVAL : 0; +- +- *nplanes = 1; +- sizes[0] = size; +- +- coda_dbg(1, ctx, "get %d buffer(s) of size %d each.\n", *nbuffers, +- size); +- +- return 0; +-} +- +-static int coda_buf_prepare(struct vb2_buffer *vb) +-{ +- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); +- struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); +- struct coda_q_data *q_data; +- +- q_data = get_q_data(ctx, vb->vb2_queue->type); +- if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { +- if (vbuf->field == V4L2_FIELD_ANY) +- vbuf->field = V4L2_FIELD_NONE; +- if (vbuf->field != V4L2_FIELD_NONE) { +- v4l2_warn(&ctx->dev->v4l2_dev, +- "%s field isn't supported\n", __func__); +- return -EINVAL; +- } +- } +- +- if (vb2_plane_size(vb, 0) < q_data->sizeimage) { +- v4l2_warn(&ctx->dev->v4l2_dev, +- "%s data will not fit into plane (%lu < %lu)\n", +- __func__, vb2_plane_size(vb, 0), +- (long)q_data->sizeimage); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static void coda_update_menu_ctrl(struct v4l2_ctrl *ctrl, int value) +-{ +- if (!ctrl) +- return; +- +- v4l2_ctrl_lock(ctrl); +- +- /* +- * Extend the control range if the parsed stream contains a known but +- * unsupported value or level. +- */ +- if (value > ctrl->maximum) { +- __v4l2_ctrl_modify_range(ctrl, ctrl->minimum, value, +- ctrl->menu_skip_mask & ~(1 << value), +- ctrl->default_value); +- } else if (value < ctrl->minimum) { +- __v4l2_ctrl_modify_range(ctrl, value, ctrl->maximum, +- ctrl->menu_skip_mask & ~(1 << value), +- ctrl->default_value); +- } +- +- __v4l2_ctrl_s_ctrl(ctrl, value); +- +- v4l2_ctrl_unlock(ctrl); +-} +- +-void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc, +- u8 level_idc) +-{ +- const char * const *profile_names; +- const char * const *level_names; +- struct v4l2_ctrl *profile_ctrl; +- struct v4l2_ctrl *level_ctrl; +- const char *codec_name; +- u32 profile_cid; +- u32 level_cid; +- int profile; +- int level; +- +- switch (ctx->codec->src_fourcc) { +- case V4L2_PIX_FMT_H264: +- codec_name = "H264"; +- profile_cid = V4L2_CID_MPEG_VIDEO_H264_PROFILE; +- level_cid = V4L2_CID_MPEG_VIDEO_H264_LEVEL; +- profile_ctrl = ctx->h264_profile_ctrl; +- level_ctrl = ctx->h264_level_ctrl; +- profile = coda_h264_profile(profile_idc); +- level = coda_h264_level(level_idc); +- break; +- case V4L2_PIX_FMT_MPEG2: +- codec_name = "MPEG-2"; +- profile_cid = V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE; +- level_cid = V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL; +- profile_ctrl = ctx->mpeg2_profile_ctrl; +- level_ctrl = ctx->mpeg2_level_ctrl; +- profile = coda_mpeg2_profile(profile_idc); +- level = coda_mpeg2_level(level_idc); +- break; +- case V4L2_PIX_FMT_MPEG4: +- codec_name = "MPEG-4"; +- profile_cid = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE; +- level_cid = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL; +- profile_ctrl = ctx->mpeg4_profile_ctrl; +- level_ctrl = ctx->mpeg4_level_ctrl; +- profile = coda_mpeg4_profile(profile_idc); +- level = coda_mpeg4_level(level_idc); +- break; +- default: +- return; +- } +- +- profile_names = v4l2_ctrl_get_menu(profile_cid); +- level_names = v4l2_ctrl_get_menu(level_cid); +- +- if (profile < 0) { +- v4l2_warn(&ctx->dev->v4l2_dev, "Invalid %s profile: %u\n", +- codec_name, profile_idc); +- } else { +- coda_dbg(1, ctx, "Parsed %s profile: %s\n", codec_name, +- profile_names[profile]); +- coda_update_menu_ctrl(profile_ctrl, profile); +- } +- +- if (level < 0) { +- v4l2_warn(&ctx->dev->v4l2_dev, "Invalid %s level: %u\n", +- codec_name, level_idc); +- } else { +- coda_dbg(1, ctx, "Parsed %s level: %s\n", codec_name, +- level_names[level]); +- coda_update_menu_ctrl(level_ctrl, level); +- } +-} +- +-static void coda_queue_source_change_event(struct coda_ctx *ctx) +-{ +- static const struct v4l2_event source_change_event = { +- .type = V4L2_EVENT_SOURCE_CHANGE, +- .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, +- }; +- +- v4l2_event_queue_fh(&ctx->fh, &source_change_event); +-} +- +-static void coda_buf_queue(struct vb2_buffer *vb) +-{ +- struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); +- struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); +- struct vb2_queue *vq = vb->vb2_queue; +- struct coda_q_data *q_data; +- +- q_data = get_q_data(ctx, vb->vb2_queue->type); +- +- /* +- * In the decoder case, immediately try to copy the buffer into the +- * bitstream ringbuffer and mark it as ready to be dequeued. +- */ +- if (ctx->bitstream.size && vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { +- /* +- * For backwards compatibility, queuing an empty buffer marks +- * the stream end +- */ +- if (vb2_get_plane_payload(vb, 0) == 0) +- coda_bit_stream_end_flag(ctx); +- +- if (q_data->fourcc == V4L2_PIX_FMT_H264) { +- /* +- * Unless already done, try to obtain profile_idc and +- * level_idc from the SPS header. This allows to decide +- * whether to enable reordering during sequence +- * initialization. +- */ +- if (!ctx->params.h264_profile_idc) { +- coda_sps_parse_profile(ctx, vb); +- coda_update_profile_level_ctrls(ctx, +- ctx->params.h264_profile_idc, +- ctx->params.h264_level_idc); +- } +- } +- +- mutex_lock(&ctx->bitstream_mutex); +- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); +- if (vb2_is_streaming(vb->vb2_queue)) +- /* This set buf->sequence = ctx->qsequence++ */ +- coda_fill_bitstream(ctx, NULL); +- mutex_unlock(&ctx->bitstream_mutex); +- +- if (!ctx->initialized) { +- /* +- * Run sequence initialization in case the queued +- * buffer contained headers. +- */ +- if (vb2_is_streaming(vb->vb2_queue) && +- ctx->ops->seq_init_work) { +- queue_work(ctx->dev->workqueue, +- &ctx->seq_init_work); +- flush_work(&ctx->seq_init_work); +- } +- +- if (ctx->initialized) +- coda_queue_source_change_event(ctx); +- } +- } else { +- if ((ctx->inst_type == CODA_INST_ENCODER || !ctx->use_bit) && +- vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) +- vbuf->sequence = ctx->qsequence++; +- v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); +- } +-} +- +-int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf, +- size_t size, const char *name, struct dentry *parent) +-{ +- buf->vaddr = dma_alloc_coherent(dev->dev, size, &buf->paddr, +- GFP_KERNEL); +- if (!buf->vaddr) { +- v4l2_err(&dev->v4l2_dev, +- "Failed to allocate %s buffer of size %zu\n", +- name, size); +- return -ENOMEM; +- } +- +- buf->size = size; +- +- if (name && parent) { +- buf->blob.data = buf->vaddr; +- buf->blob.size = size; +- buf->dentry = debugfs_create_blob(name, 0444, parent, +- &buf->blob); +- } +- +- return 0; +-} +- +-void coda_free_aux_buf(struct coda_dev *dev, +- struct coda_aux_buf *buf) +-{ +- if (buf->vaddr) { +- dma_free_coherent(dev->dev, buf->size, buf->vaddr, buf->paddr); +- buf->vaddr = NULL; +- buf->size = 0; +- debugfs_remove(buf->dentry); +- buf->dentry = NULL; +- } +-} +- +-static int coda_start_streaming(struct vb2_queue *q, unsigned int count) +-{ +- struct coda_ctx *ctx = vb2_get_drv_priv(q); +- struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev; +- struct coda_q_data *q_data_src, *q_data_dst; +- struct v4l2_m2m_buffer *m2m_buf, *tmp; +- struct vb2_v4l2_buffer *buf; +- struct list_head list; +- int ret = 0; +- +- if (count < 1) +- return -EINVAL; +- +- coda_dbg(1, ctx, "start streaming %s\n", v4l2_type_names[q->type]); +- +- INIT_LIST_HEAD(&list); +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { +- if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) { +- /* copy the buffers that were queued before streamon */ +- mutex_lock(&ctx->bitstream_mutex); +- coda_fill_bitstream(ctx, &list); +- mutex_unlock(&ctx->bitstream_mutex); +- +- if (ctx->dev->devtype->product != CODA_960 && +- coda_get_bitstream_payload(ctx) < 512) { +- v4l2_err(v4l2_dev, "start payload < 512\n"); +- ret = -EINVAL; +- goto err; +- } +- +- if (!ctx->initialized) { +- /* Run sequence initialization */ +- if (ctx->ops->seq_init_work) { +- queue_work(ctx->dev->workqueue, +- &ctx->seq_init_work); +- flush_work(&ctx->seq_init_work); +- } +- } +- } +- +- /* +- * Check the first input JPEG buffer to determine chroma +- * subsampling. +- */ +- if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) { +- buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); +- coda_jpeg_decode_header(ctx, &buf->vb2_buf); +- /* +- * We have to start streaming even if the first buffer +- * does not contain a valid JPEG image. The error will +- * be caught during device run and will be signalled +- * via the capture buffer error flag. +- */ +- +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- q_data_dst->width = round_up(q_data_src->width, 16); +- q_data_dst->height = round_up(q_data_src->height, 16); +- q_data_dst->bytesperline = q_data_dst->width; +- if (ctx->params.jpeg_chroma_subsampling == +- V4L2_JPEG_CHROMA_SUBSAMPLING_420) { +- q_data_dst->sizeimage = +- q_data_dst->bytesperline * +- q_data_dst->height * 3 / 2; +- if (q_data_dst->fourcc != V4L2_PIX_FMT_YUV420) +- q_data_dst->fourcc = V4L2_PIX_FMT_NV12; +- } else { +- q_data_dst->sizeimage = +- q_data_dst->bytesperline * +- q_data_dst->height * 2; +- q_data_dst->fourcc = V4L2_PIX_FMT_YUV422P; +- } +- q_data_dst->rect.left = 0; +- q_data_dst->rect.top = 0; +- q_data_dst->rect.width = q_data_src->width; +- q_data_dst->rect.height = q_data_src->height; +- } +- ctx->streamon_out = 1; +- } else { +- ctx->streamon_cap = 1; +- } +- +- /* Don't start the coda unless both queues are on */ +- if (!(ctx->streamon_out && ctx->streamon_cap)) +- goto out; +- +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- if ((q_data_src->rect.width != q_data_dst->width && +- round_up(q_data_src->rect.width, 16) != q_data_dst->width) || +- (q_data_src->rect.height != q_data_dst->height && +- round_up(q_data_src->rect.height, 16) != q_data_dst->height)) { +- v4l2_err(v4l2_dev, "can't convert %dx%d to %dx%d\n", +- q_data_src->rect.width, q_data_src->rect.height, +- q_data_dst->width, q_data_dst->height); +- ret = -EINVAL; +- goto err; +- } +- +- /* Allow BIT decoder device_run with no new buffers queued */ +- if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) +- v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true); +- +- ctx->gopcounter = ctx->params.gop_size - 1; +- +- if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG) +- ctx->params.gop_size = 1; +- ctx->gopcounter = ctx->params.gop_size - 1; +- /* Only decoders have this control */ +- if (ctx->mb_err_cnt_ctrl) +- v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, 0); +- +- ret = ctx->ops->start_streaming(ctx); +- if (ctx->inst_type == CODA_INST_DECODER) { +- if (ret == -EAGAIN) +- goto out; +- } +- if (ret < 0) +- goto err; +- +-out: +- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { +- list_for_each_entry_safe(m2m_buf, tmp, &list, list) { +- list_del(&m2m_buf->list); +- v4l2_m2m_buf_done(&m2m_buf->vb, VB2_BUF_STATE_DONE); +- } +- } +- return 0; +- +-err: +- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { +- list_for_each_entry_safe(m2m_buf, tmp, &list, list) { +- list_del(&m2m_buf->list); +- v4l2_m2m_buf_done(&m2m_buf->vb, VB2_BUF_STATE_QUEUED); +- } +- while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) +- v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED); +- } else { +- while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) +- v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED); +- } +- return ret; +-} +- +-static void coda_stop_streaming(struct vb2_queue *q) +-{ +- struct coda_ctx *ctx = vb2_get_drv_priv(q); +- struct coda_dev *dev = ctx->dev; +- struct vb2_v4l2_buffer *buf; +- bool stop; +- +- stop = ctx->streamon_out && ctx->streamon_cap; +- +- coda_dbg(1, ctx, "stop streaming %s\n", v4l2_type_names[q->type]); +- +- if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { +- ctx->streamon_out = 0; +- +- coda_bit_stream_end_flag(ctx); +- +- ctx->qsequence = 0; +- +- while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) +- v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); +- } else { +- ctx->streamon_cap = 0; +- +- ctx->osequence = 0; +- ctx->sequence_offset = 0; +- +- while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) +- v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); +- } +- +- if (stop) { +- struct coda_buffer_meta *meta; +- +- if (ctx->ops->seq_end_work) { +- queue_work(dev->workqueue, &ctx->seq_end_work); +- flush_work(&ctx->seq_end_work); +- } +- spin_lock(&ctx->buffer_meta_lock); +- while (!list_empty(&ctx->buffer_meta_list)) { +- meta = list_first_entry(&ctx->buffer_meta_list, +- struct coda_buffer_meta, list); +- list_del(&meta->list); +- kfree(meta); +- } +- ctx->num_metas = 0; +- spin_unlock(&ctx->buffer_meta_lock); +- kfifo_init(&ctx->bitstream_fifo, +- ctx->bitstream.vaddr, ctx->bitstream.size); +- ctx->runcounter = 0; +- ctx->aborting = 0; +- ctx->hold = false; +- } +- +- if (!ctx->streamon_out && !ctx->streamon_cap) +- ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG; +-} +- +-static const struct vb2_ops coda_qops = { +- .queue_setup = coda_queue_setup, +- .buf_prepare = coda_buf_prepare, +- .buf_queue = coda_buf_queue, +- .start_streaming = coda_start_streaming, +- .stop_streaming = coda_stop_streaming, +- .wait_prepare = vb2_ops_wait_prepare, +- .wait_finish = vb2_ops_wait_finish, +-}; +- +-static int coda_s_ctrl(struct v4l2_ctrl *ctrl) +-{ +- const char * const *val_names = v4l2_ctrl_get_menu(ctrl->id); +- struct coda_ctx *ctx = +- container_of(ctrl->handler, struct coda_ctx, ctrls); +- +- if (val_names) +- coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d (\"%s\")\n", +- ctrl->id, ctrl->name, ctrl->val, val_names[ctrl->val]); +- else +- coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d\n", +- ctrl->id, ctrl->name, ctrl->val); +- +- switch (ctrl->id) { +- case V4L2_CID_HFLIP: +- if (ctrl->val) +- ctx->params.rot_mode |= CODA_MIR_HOR; +- else +- ctx->params.rot_mode &= ~CODA_MIR_HOR; +- break; +- case V4L2_CID_VFLIP: +- if (ctrl->val) +- ctx->params.rot_mode |= CODA_MIR_VER; +- else +- ctx->params.rot_mode &= ~CODA_MIR_VER; +- break; +- case V4L2_CID_MPEG_VIDEO_BITRATE: +- ctx->params.bitrate = ctrl->val / 1000; +- ctx->params.bitrate_changed = true; +- break; +- case V4L2_CID_MPEG_VIDEO_GOP_SIZE: +- ctx->params.gop_size = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: +- ctx->params.h264_intra_qp = ctrl->val; +- ctx->params.h264_intra_qp_changed = true; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP: +- ctx->params.h264_inter_qp = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: +- ctx->params.h264_min_qp = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: +- ctx->params.h264_max_qp = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: +- ctx->params.h264_slice_alpha_c0_offset_div2 = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: +- ctx->params.h264_slice_beta_offset_div2 = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: +- ctx->params.h264_disable_deblocking_filter_idc = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION: +- ctx->params.h264_constrained_intra_pred_flag = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: +- ctx->params.frame_rc_enable = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: +- ctx->params.mb_rc_enable = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET: +- ctx->params.h264_chroma_qp_index_offset = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_PROFILE: +- /* TODO: switch between baseline and constrained baseline */ +- if (ctx->inst_type == CODA_INST_ENCODER) +- ctx->params.h264_profile_idc = 66; +- break; +- case V4L2_CID_MPEG_VIDEO_H264_LEVEL: +- /* nothing to do, this is set by the encoder */ +- break; +- case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP: +- ctx->params.mpeg4_intra_qp = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP: +- ctx->params.mpeg4_inter_qp = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE: +- case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL: +- case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: +- case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: +- /* nothing to do, these are fixed */ +- break; +- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: +- ctx->params.slice_mode = ctrl->val; +- ctx->params.slice_mode_changed = true; +- break; +- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: +- ctx->params.slice_max_mb = ctrl->val; +- ctx->params.slice_mode_changed = true; +- break; +- case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES: +- ctx->params.slice_max_bits = ctrl->val * 8; +- ctx->params.slice_mode_changed = true; +- break; +- case V4L2_CID_MPEG_VIDEO_HEADER_MODE: +- break; +- case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: +- ctx->params.intra_refresh = ctrl->val; +- ctx->params.intra_refresh_changed = true; +- break; +- case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: +- ctx->params.force_ipicture = true; +- break; +- case V4L2_CID_JPEG_COMPRESSION_QUALITY: +- coda_set_jpeg_compression_quality(ctx, ctrl->val); +- break; +- case V4L2_CID_JPEG_RESTART_INTERVAL: +- ctx->params.jpeg_restart_interval = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_VBV_DELAY: +- ctx->params.vbv_delay = ctrl->val; +- break; +- case V4L2_CID_MPEG_VIDEO_VBV_SIZE: +- ctx->params.vbv_size = min(ctrl->val * 8192, 0x7fffffff); +- break; +- default: +- coda_dbg(1, ctx, "Invalid control, id=%d, val=%d\n", +- ctrl->id, ctrl->val); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static const struct v4l2_ctrl_ops coda_ctrl_ops = { +- .s_ctrl = coda_s_ctrl, +-}; +- +-static void coda_encode_ctrls(struct coda_ctx *ctx) +-{ +- int max_gop_size = (ctx->dev->devtype->product == CODA_DX6) ? 60 : 99; +- +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1000, 0); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, max_gop_size, 1, 16); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25); +- if (ctx->dev->devtype->product != CODA_960) { +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 51, 1, 12); +- } +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, -6, 6, 1, 0); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0); +- v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, +- V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY, +- 0x0, V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION, 0, 1, 1, +- 0); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, 0, 1, 1, 1); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, -12, 12, 1, 0); +- v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_PROFILE, +- V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, 0x0, +- V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE); +- if (ctx->dev->devtype->product == CODA_HX4 || +- ctx->dev->devtype->product == CODA_7541) { +- v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_LEVEL, +- V4L2_MPEG_VIDEO_H264_LEVEL_3_1, +- ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1)), +- V4L2_MPEG_VIDEO_H264_LEVEL_3_1); +- } +- if (ctx->dev->devtype->product == CODA_960) { +- v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_H264_LEVEL, +- V4L2_MPEG_VIDEO_H264_LEVEL_4_2, +- ~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | +- (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2)), +- V4L2_MPEG_VIDEO_H264_LEVEL_4_0); +- } +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, 1, 31, 1, 2); +- v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, +- V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE, 0x0, +- V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE); +- if (ctx->dev->devtype->product == CODA_HX4 || +- ctx->dev->devtype->product == CODA_7541 || +- ctx->dev->devtype->product == CODA_960) { +- v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, +- V4L2_MPEG_VIDEO_MPEG4_LEVEL_5, +- ~(1 << V4L2_MPEG_VIDEO_MPEG4_LEVEL_5), +- V4L2_MPEG_VIDEO_MPEG4_LEVEL_5); +- } +- v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, +- V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES, 0x0, +- V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, 1, 0x3fffffff, 1, 1); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, 1, 0x3fffffff, 1, +- 500); +- v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_HEADER_MODE, +- V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, +- (1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE), +- V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0, +- 1920 * 1088 / 256, 1, 0); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_VBV_DELAY, 0, 0x7fff, 1, 0); +- /* +- * The maximum VBV size value is 0x7fffffff bits, +- * one bit less than 262144 KiB +- */ +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_VBV_SIZE, 0, 262144, 1, 0); +-} +- +-static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx) +-{ +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_JPEG_COMPRESSION_QUALITY, 5, 100, 1, 50); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_JPEG_RESTART_INTERVAL, 0, 100, 1, 0); +-} +- +-static void coda_decode_ctrls(struct coda_ctx *ctx) +-{ +- u8 max; +- +- ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, +- &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE, +- V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, +- ~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | +- (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | +- (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)), +- V4L2_MPEG_VIDEO_H264_PROFILE_HIGH); +- if (ctx->h264_profile_ctrl) +- ctx->h264_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- +- if (ctx->dev->devtype->product == CODA_HX4 || +- ctx->dev->devtype->product == CODA_7541) +- max = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; +- else if (ctx->dev->devtype->product == CODA_960) +- max = V4L2_MPEG_VIDEO_H264_LEVEL_4_1; +- else +- return; +- ctx->h264_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, +- &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL, max, 0, max); +- if (ctx->h264_level_ctrl) +- ctx->h264_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- +- ctx->mpeg2_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, +- &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE, +- V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH, 0, +- V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH); +- if (ctx->mpeg2_profile_ctrl) +- ctx->mpeg2_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- +- ctx->mpeg2_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, +- &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL, +- V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH, 0, +- V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH); +- if (ctx->mpeg2_level_ctrl) +- ctx->mpeg2_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- +- ctx->mpeg4_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, +- &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, +- V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY, 0, +- V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY); +- if (ctx->mpeg4_profile_ctrl) +- ctx->mpeg4_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- +- ctx->mpeg4_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls, +- &coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, +- V4L2_MPEG_VIDEO_MPEG4_LEVEL_5, 0, +- V4L2_MPEG_VIDEO_MPEG4_LEVEL_5); +- if (ctx->mpeg4_level_ctrl) +- ctx->mpeg4_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; +-} +- +-static const struct v4l2_ctrl_config coda_mb_err_cnt_ctrl_config = { +- .id = V4L2_CID_CODA_MB_ERR_CNT, +- .name = "Macroblocks Error Count", +- .type = V4L2_CTRL_TYPE_INTEGER, +- .min = 0, +- .max = 0x7fffffff, +- .step = 1, +-}; +- +-static int coda_ctrls_setup(struct coda_ctx *ctx) +-{ +- v4l2_ctrl_handler_init(&ctx->ctrls, 2); +- +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_HFLIP, 0, 1, 1, 0); +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_VFLIP, 0, 1, 1, 0); +- if (ctx->inst_type == CODA_INST_ENCODER) { +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, +- 1, 1, 1, 1); +- if (ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG) +- coda_jpeg_encode_ctrls(ctx); +- else +- coda_encode_ctrls(ctx); +- } else { +- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops, +- V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, +- 1, 1, 1, 1); +- if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_H264) +- coda_decode_ctrls(ctx); +- +- ctx->mb_err_cnt_ctrl = v4l2_ctrl_new_custom(&ctx->ctrls, +- &coda_mb_err_cnt_ctrl_config, +- NULL); +- if (ctx->mb_err_cnt_ctrl) +- ctx->mb_err_cnt_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- } +- +- if (ctx->ctrls.error) { +- v4l2_err(&ctx->dev->v4l2_dev, +- "control initialization error (%d)", +- ctx->ctrls.error); +- return -EINVAL; +- } +- +- return v4l2_ctrl_handler_setup(&ctx->ctrls); +-} +- +-static int coda_queue_init(struct coda_ctx *ctx, struct vb2_queue *vq) +-{ +- vq->drv_priv = ctx; +- vq->ops = &coda_qops; +- vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); +- vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; +- vq->lock = &ctx->dev->dev_mutex; +- /* One way to indicate end-of-stream for coda is to set the +- * bytesused == 0. However by default videobuf2 handles bytesused +- * equal to 0 as a special case and changes its value to the size +- * of the buffer. Set the allow_zero_bytesused flag, so +- * that videobuf2 will keep the value of bytesused intact. +- */ +- vq->allow_zero_bytesused = 1; +- /* +- * We might be fine with no buffers on some of the queues, but that +- * would need to be reflected in job_ready(). Currently we expect all +- * queues to have at least one buffer queued. +- */ +- vq->min_buffers_needed = 1; +- vq->dev = ctx->dev->dev; +- +- return vb2_queue_init(vq); +-} +- +-int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, +- struct vb2_queue *dst_vq) +-{ +- int ret; +- +- src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; +- src_vq->io_modes = VB2_DMABUF | VB2_MMAP; +- src_vq->mem_ops = &vb2_dma_contig_memops; +- +- ret = coda_queue_init(priv, src_vq); +- if (ret) +- return ret; +- +- dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +- dst_vq->io_modes = VB2_DMABUF | VB2_MMAP; +- dst_vq->mem_ops = &vb2_dma_contig_memops; +- +- return coda_queue_init(priv, dst_vq); +-} +- +-int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, +- struct vb2_queue *dst_vq) +-{ +- int ret; +- +- src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; +- src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR; +- src_vq->mem_ops = &vb2_vmalloc_memops; +- +- ret = coda_queue_init(priv, src_vq); +- if (ret) +- return ret; +- +- dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +- dst_vq->io_modes = VB2_DMABUF | VB2_MMAP; +- dst_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING; +- dst_vq->mem_ops = &vb2_dma_contig_memops; +- +- return coda_queue_init(priv, dst_vq); +-} +- +-/* +- * File operations +- */ +- +-static int coda_open(struct file *file) +-{ +- struct video_device *vdev = video_devdata(file); +- struct coda_dev *dev = video_get_drvdata(vdev); +- struct coda_ctx *ctx; +- unsigned int max = ~0; +- char *name; +- int ret; +- int idx; +- +- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); +- if (!ctx) +- return -ENOMEM; +- +- if (dev->devtype->product == CODA_DX6) +- max = CODADX6_MAX_INSTANCES - 1; +- idx = ida_alloc_max(&dev->ida, max, GFP_KERNEL); +- if (idx < 0) { +- ret = idx; +- goto err_coda_max; +- } +- +- name = kasprintf(GFP_KERNEL, "context%d", idx); +- if (!name) { +- ret = -ENOMEM; +- goto err_coda_name_init; +- } +- +- ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root); +- kfree(name); +- +- ctx->cvd = to_coda_video_device(vdev); +- ctx->inst_type = ctx->cvd->type; +- ctx->ops = ctx->cvd->ops; +- ctx->use_bit = !ctx->cvd->direct; +- init_completion(&ctx->completion); +- INIT_WORK(&ctx->pic_run_work, coda_pic_run_work); +- if (ctx->ops->seq_init_work) +- INIT_WORK(&ctx->seq_init_work, ctx->ops->seq_init_work); +- if (ctx->ops->seq_end_work) +- INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work); +- v4l2_fh_init(&ctx->fh, video_devdata(file)); +- file->private_data = &ctx->fh; +- v4l2_fh_add(&ctx->fh); +- ctx->dev = dev; +- ctx->idx = idx; +- +- coda_dbg(1, ctx, "open instance (%p)\n", ctx); +- +- switch (dev->devtype->product) { +- case CODA_960: +- /* +- * Enabling the BWB when decoding can hang the firmware with +- * certain streams. The issue was tracked as ENGR00293425 by +- * Freescale. As a workaround, disable BWB for all decoders. +- * The enable_bwb module parameter allows to override this. +- */ +- if (enable_bwb || ctx->inst_type == CODA_INST_ENCODER) +- ctx->frame_mem_ctrl = CODA9_FRAME_ENABLE_BWB; +- fallthrough; +- case CODA_HX4: +- case CODA_7541: +- ctx->reg_idx = 0; +- break; +- default: +- ctx->reg_idx = idx; +- } +- if (ctx->dev->vdoa && !disable_vdoa) { +- ctx->vdoa = vdoa_context_create(dev->vdoa); +- if (!ctx->vdoa) +- v4l2_warn(&dev->v4l2_dev, +- "Failed to create vdoa context: not using vdoa"); +- } +- ctx->use_vdoa = false; +- +- /* Power up and upload firmware if necessary */ +- ret = pm_runtime_resume_and_get(dev->dev); +- if (ret < 0) { +- v4l2_err(&dev->v4l2_dev, "failed to power up: %d\n", ret); +- goto err_pm_get; +- } +- +- ret = clk_prepare_enable(dev->clk_per); +- if (ret) +- goto err_clk_enable; +- +- ret = clk_prepare_enable(dev->clk_ahb); +- if (ret) +- goto err_clk_ahb; +- +- set_default_params(ctx); +- ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, +- ctx->ops->queue_init); +- if (IS_ERR(ctx->fh.m2m_ctx)) { +- ret = PTR_ERR(ctx->fh.m2m_ctx); +- +- v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n", +- __func__, ret); +- goto err_ctx_init; +- } +- +- ret = coda_ctrls_setup(ctx); +- if (ret) { +- v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n"); +- goto err_ctrls_setup; +- } +- +- ctx->fh.ctrl_handler = &ctx->ctrls; +- +- mutex_init(&ctx->bitstream_mutex); +- mutex_init(&ctx->buffer_mutex); +- mutex_init(&ctx->wakeup_mutex); +- INIT_LIST_HEAD(&ctx->buffer_meta_list); +- spin_lock_init(&ctx->buffer_meta_lock); +- +- return 0; +- +-err_ctrls_setup: +- v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); +-err_ctx_init: +- clk_disable_unprepare(dev->clk_ahb); +-err_clk_ahb: +- clk_disable_unprepare(dev->clk_per); +-err_clk_enable: +- pm_runtime_put_sync(dev->dev); +-err_pm_get: +- v4l2_fh_del(&ctx->fh); +- v4l2_fh_exit(&ctx->fh); +-err_coda_name_init: +- ida_free(&dev->ida, ctx->idx); +-err_coda_max: +- kfree(ctx); +- return ret; +-} +- +-static int coda_release(struct file *file) +-{ +- struct coda_dev *dev = video_drvdata(file); +- struct coda_ctx *ctx = fh_to_ctx(file->private_data); +- +- coda_dbg(1, ctx, "release instance (%p)\n", ctx); +- +- if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) +- coda_bit_stream_end_flag(ctx); +- +- /* If this instance is running, call .job_abort and wait for it to end */ +- v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); +- +- if (ctx->vdoa) +- vdoa_context_destroy(ctx->vdoa); +- +- /* In case the instance was not running, we still need to call SEQ_END */ +- if (ctx->ops->seq_end_work) { +- queue_work(dev->workqueue, &ctx->seq_end_work); +- flush_work(&ctx->seq_end_work); +- } +- +- if (ctx->dev->devtype->product == CODA_DX6) +- coda_free_aux_buf(dev, &ctx->workbuf); +- +- v4l2_ctrl_handler_free(&ctx->ctrls); +- clk_disable_unprepare(dev->clk_ahb); +- clk_disable_unprepare(dev->clk_per); +- pm_runtime_put_sync(dev->dev); +- v4l2_fh_del(&ctx->fh); +- v4l2_fh_exit(&ctx->fh); +- ida_free(&dev->ida, ctx->idx); +- if (ctx->ops->release) +- ctx->ops->release(ctx); +- debugfs_remove_recursive(ctx->debugfs_entry); +- kfree(ctx); +- +- return 0; +-} +- +-static const struct v4l2_file_operations coda_fops = { +- .owner = THIS_MODULE, +- .open = coda_open, +- .release = coda_release, +- .poll = v4l2_m2m_fop_poll, +- .unlocked_ioctl = video_ioctl2, +- .mmap = v4l2_m2m_fop_mmap, +-}; +- +-static int coda_hw_init(struct coda_dev *dev) +-{ +- u32 data; +- u16 *p; +- int i, ret; +- +- ret = clk_prepare_enable(dev->clk_per); +- if (ret) +- goto err_clk_per; +- +- ret = clk_prepare_enable(dev->clk_ahb); +- if (ret) +- goto err_clk_ahb; +- +- reset_control_reset(dev->rstc); +- +- /* +- * Copy the first CODA_ISRAM_SIZE in the internal SRAM. +- * The 16-bit chars in the code buffer are in memory access +- * order, re-sort them to CODA order for register download. +- * Data in this SRAM survives a reboot. +- */ +- p = (u16 *)dev->codebuf.vaddr; +- if (dev->devtype->product == CODA_DX6) { +- for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) { +- data = CODA_DOWN_ADDRESS_SET(i) | +- CODA_DOWN_DATA_SET(p[i ^ 1]); +- coda_write(dev, data, CODA_REG_BIT_CODE_DOWN); +- } +- } else { +- for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) { +- data = CODA_DOWN_ADDRESS_SET(i) | +- CODA_DOWN_DATA_SET(p[round_down(i, 4) + +- 3 - (i % 4)]); +- coda_write(dev, data, CODA_REG_BIT_CODE_DOWN); +- } +- } +- +- /* Clear registers */ +- for (i = 0; i < 64; i++) +- coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4); +- +- /* Tell the BIT where to find everything it needs */ +- if (dev->devtype->product == CODA_960 || +- dev->devtype->product == CODA_7541 || +- dev->devtype->product == CODA_HX4) { +- coda_write(dev, dev->tempbuf.paddr, +- CODA_REG_BIT_TEMP_BUF_ADDR); +- coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM); +- } else { +- coda_write(dev, dev->workbuf.paddr, +- CODA_REG_BIT_WORK_BUF_ADDR); +- } +- coda_write(dev, dev->codebuf.paddr, +- CODA_REG_BIT_CODE_BUF_ADDR); +- coda_write(dev, 0, CODA_REG_BIT_CODE_RUN); +- +- /* Set default values */ +- switch (dev->devtype->product) { +- case CODA_DX6: +- coda_write(dev, CODADX6_STREAM_BUF_PIC_FLUSH, +- CODA_REG_BIT_STREAM_CTRL); +- break; +- default: +- coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH, +- CODA_REG_BIT_STREAM_CTRL); +- } +- if (dev->devtype->product == CODA_960) +- coda_write(dev, CODA9_FRAME_ENABLE_BWB, +- CODA_REG_BIT_FRAME_MEM_CTRL); +- else +- coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL); +- +- if (dev->devtype->product != CODA_DX6) +- coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE); +- +- coda_write(dev, CODA_INT_INTERRUPT_ENABLE, +- CODA_REG_BIT_INT_ENABLE); +- +- /* Reset VPU and start processor */ +- data = coda_read(dev, CODA_REG_BIT_CODE_RESET); +- data |= CODA_REG_RESET_ENABLE; +- coda_write(dev, data, CODA_REG_BIT_CODE_RESET); +- udelay(10); +- data &= ~CODA_REG_RESET_ENABLE; +- coda_write(dev, data, CODA_REG_BIT_CODE_RESET); +- coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN); +- +- clk_disable_unprepare(dev->clk_ahb); +- clk_disable_unprepare(dev->clk_per); +- +- return 0; +- +-err_clk_ahb: +- clk_disable_unprepare(dev->clk_per); +-err_clk_per: +- return ret; +-} +- +-static int coda_register_device(struct coda_dev *dev, int i) +-{ +- struct video_device *vfd = &dev->vfd[i]; +- const char *name; +- int ret; +- +- if (i >= dev->devtype->num_vdevs) +- return -EINVAL; +- name = dev->devtype->vdevs[i]->name; +- +- strscpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name)); +- vfd->fops = &coda_fops; +- vfd->ioctl_ops = &coda_ioctl_ops; +- vfd->release = video_device_release_empty; +- vfd->lock = &dev->dev_mutex; +- vfd->v4l2_dev = &dev->v4l2_dev; +- vfd->vfl_dir = VFL_DIR_M2M; +- vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; +- video_set_drvdata(vfd, dev); +- +- /* Not applicable, use the selection API instead */ +- v4l2_disable_ioctl(vfd, VIDIOC_CROPCAP); +- v4l2_disable_ioctl(vfd, VIDIOC_G_CROP); +- v4l2_disable_ioctl(vfd, VIDIOC_S_CROP); +- +- if (dev->devtype->vdevs[i]->type == CODA_INST_ENCODER) { +- v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD); +- v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD); +- if (dev->devtype->vdevs[i]->dst_formats[0] == V4L2_PIX_FMT_JPEG) { +- v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS); +- v4l2_disable_ioctl(vfd, VIDIOC_G_PARM); +- v4l2_disable_ioctl(vfd, VIDIOC_S_PARM); +- } +- } else { +- v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD); +- v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD); +- v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMESIZES); +- v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS); +- v4l2_disable_ioctl(vfd, VIDIOC_G_PARM); +- v4l2_disable_ioctl(vfd, VIDIOC_S_PARM); +- } +- +- ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); +- if (!ret) +- v4l2_info(&dev->v4l2_dev, "%s registered as %s\n", +- name, video_device_node_name(vfd)); +- return ret; +-} +- +-static void coda_copy_firmware(struct coda_dev *dev, const u8 * const buf, +- size_t size) +-{ +- u32 *src = (u32 *)buf; +- +- /* Check if the firmware has a 16-byte Freescale header, skip it */ +- if (buf[0] == 'M' && buf[1] == 'X') +- src += 4; +- /* +- * Check whether the firmware is in native order or pre-reordered for +- * memory access. The first instruction opcode always is 0xe40e. +- */ +- if (__le16_to_cpup((__le16 *)src) == 0xe40e) { +- u32 *dst = dev->codebuf.vaddr; +- int i; +- +- /* Firmware in native order, reorder while copying */ +- if (dev->devtype->product == CODA_DX6) { +- for (i = 0; i < (size - 16) / 4; i++) +- dst[i] = (src[i] << 16) | (src[i] >> 16); +- } else { +- for (i = 0; i < (size - 16) / 4; i += 2) { +- dst[i] = (src[i + 1] << 16) | (src[i + 1] >> 16); +- dst[i + 1] = (src[i] << 16) | (src[i] >> 16); +- } +- } +- } else { +- /* Copy the already reordered firmware image */ +- memcpy(dev->codebuf.vaddr, src, size); +- } +-} +- +-static void coda_fw_callback(const struct firmware *fw, void *context); +- +-static int coda_firmware_request(struct coda_dev *dev) +-{ +- char *fw; +- +- if (dev->firmware >= ARRAY_SIZE(dev->devtype->firmware)) +- return -EINVAL; +- +- fw = dev->devtype->firmware[dev->firmware]; +- +- dev_dbg(dev->dev, "requesting firmware '%s' for %s\n", fw, +- coda_product_name(dev->devtype->product)); +- +- return request_firmware_nowait(THIS_MODULE, true, fw, dev->dev, +- GFP_KERNEL, dev, coda_fw_callback); +-} +- +-static void coda_fw_callback(const struct firmware *fw, void *context) +-{ +- struct coda_dev *dev = context; +- int i, ret; +- +- if (!fw) { +- dev->firmware++; +- ret = coda_firmware_request(dev); +- if (ret < 0) { +- v4l2_err(&dev->v4l2_dev, "firmware request failed\n"); +- goto put_pm; +- } +- return; +- } +- if (dev->firmware > 0) { +- /* +- * Since we can't suppress warnings for failed asynchronous +- * firmware requests, report that the fallback firmware was +- * found. +- */ +- dev_info(dev->dev, "Using fallback firmware %s\n", +- dev->devtype->firmware[dev->firmware]); +- } +- +- /* allocate auxiliary per-device code buffer for the BIT processor */ +- ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf", +- dev->debugfs_root); +- if (ret < 0) +- goto put_pm; +- +- coda_copy_firmware(dev, fw->data, fw->size); +- release_firmware(fw); +- +- ret = coda_hw_init(dev); +- if (ret < 0) { +- v4l2_err(&dev->v4l2_dev, "HW initialization failed\n"); +- goto put_pm; +- } +- +- ret = coda_check_firmware(dev); +- if (ret < 0) +- goto put_pm; +- +- dev->m2m_dev = v4l2_m2m_init(&coda_m2m_ops); +- if (IS_ERR(dev->m2m_dev)) { +- v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); +- goto put_pm; +- } +- +- for (i = 0; i < dev->devtype->num_vdevs; i++) { +- ret = coda_register_device(dev, i); +- if (ret) { +- v4l2_err(&dev->v4l2_dev, +- "Failed to register %s video device: %d\n", +- dev->devtype->vdevs[i]->name, ret); +- goto rel_vfd; +- } +- } +- +- pm_runtime_put_sync(dev->dev); +- return; +- +-rel_vfd: +- while (--i >= 0) +- video_unregister_device(&dev->vfd[i]); +- v4l2_m2m_release(dev->m2m_dev); +-put_pm: +- pm_runtime_put_sync(dev->dev); +-} +- +-enum coda_platform { +- CODA_IMX27, +- CODA_IMX51, +- CODA_IMX53, +- CODA_IMX6Q, +- CODA_IMX6DL, +-}; +- +-static const struct coda_devtype coda_devdata[] = { +- [CODA_IMX27] = { +- .firmware = { +- "vpu_fw_imx27_TO2.bin", +- "vpu/vpu_fw_imx27_TO2.bin", +- "v4l-codadx6-imx27.bin" +- }, +- .product = CODA_DX6, +- .codecs = codadx6_codecs, +- .num_codecs = ARRAY_SIZE(codadx6_codecs), +- .vdevs = codadx6_video_devices, +- .num_vdevs = ARRAY_SIZE(codadx6_video_devices), +- .workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024, +- .iram_size = 0xb000, +- }, +- [CODA_IMX51] = { +- .firmware = { +- "vpu_fw_imx51.bin", +- "vpu/vpu_fw_imx51.bin", +- "v4l-codahx4-imx51.bin" +- }, +- .product = CODA_HX4, +- .codecs = codahx4_codecs, +- .num_codecs = ARRAY_SIZE(codahx4_codecs), +- .vdevs = codahx4_video_devices, +- .num_vdevs = ARRAY_SIZE(codahx4_video_devices), +- .workbuf_size = 128 * 1024, +- .tempbuf_size = 304 * 1024, +- .iram_size = 0x14000, +- }, +- [CODA_IMX53] = { +- .firmware = { +- "vpu_fw_imx53.bin", +- "vpu/vpu_fw_imx53.bin", +- "v4l-coda7541-imx53.bin" +- }, +- .product = CODA_7541, +- .codecs = coda7_codecs, +- .num_codecs = ARRAY_SIZE(coda7_codecs), +- .vdevs = coda7_video_devices, +- .num_vdevs = ARRAY_SIZE(coda7_video_devices), +- .workbuf_size = 128 * 1024, +- .tempbuf_size = 304 * 1024, +- .iram_size = 0x14000, +- }, +- [CODA_IMX6Q] = { +- .firmware = { +- "vpu_fw_imx6q.bin", +- "vpu/vpu_fw_imx6q.bin", +- "v4l-coda960-imx6q.bin" +- }, +- .product = CODA_960, +- .codecs = coda9_codecs, +- .num_codecs = ARRAY_SIZE(coda9_codecs), +- .vdevs = coda9_video_devices, +- .num_vdevs = ARRAY_SIZE(coda9_video_devices), +- .workbuf_size = 80 * 1024, +- .tempbuf_size = 204 * 1024, +- .iram_size = 0x21000, +- }, +- [CODA_IMX6DL] = { +- .firmware = { +- "vpu_fw_imx6d.bin", +- "vpu/vpu_fw_imx6d.bin", +- "v4l-coda960-imx6dl.bin" +- }, +- .product = CODA_960, +- .codecs = coda9_codecs, +- .num_codecs = ARRAY_SIZE(coda9_codecs), +- .vdevs = coda9_video_devices, +- .num_vdevs = ARRAY_SIZE(coda9_video_devices), +- .workbuf_size = 80 * 1024, +- .tempbuf_size = 204 * 1024, +- .iram_size = 0x1f000, /* leave 4k for suspend code */ +- }, +-}; +- +-static const struct of_device_id coda_dt_ids[] = { +- { .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] }, +- { .compatible = "fsl,imx51-vpu", .data = &coda_devdata[CODA_IMX51] }, +- { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] }, +- { .compatible = "fsl,imx6q-vpu", .data = &coda_devdata[CODA_IMX6Q] }, +- { .compatible = "fsl,imx6dl-vpu", .data = &coda_devdata[CODA_IMX6DL] }, +- { /* sentinel */ } +-}; +-MODULE_DEVICE_TABLE(of, coda_dt_ids); +- +-static int coda_probe(struct platform_device *pdev) +-{ +- struct device_node *np = pdev->dev.of_node; +- struct gen_pool *pool; +- struct coda_dev *dev; +- int ret, irq; +- +- dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); +- if (!dev) +- return -ENOMEM; +- +- dev->devtype = of_device_get_match_data(&pdev->dev); +- +- dev->dev = &pdev->dev; +- dev->clk_per = devm_clk_get(&pdev->dev, "per"); +- if (IS_ERR(dev->clk_per)) { +- dev_err(&pdev->dev, "Could not get per clock\n"); +- return PTR_ERR(dev->clk_per); +- } +- +- dev->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); +- if (IS_ERR(dev->clk_ahb)) { +- dev_err(&pdev->dev, "Could not get ahb clock\n"); +- return PTR_ERR(dev->clk_ahb); +- } +- +- /* Get memory for physical registers */ +- dev->regs_base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(dev->regs_base)) +- return PTR_ERR(dev->regs_base); +- +- /* IRQ */ +- irq = platform_get_irq_byname(pdev, "bit"); +- if (irq < 0) +- irq = platform_get_irq(pdev, 0); +- if (irq < 0) +- return irq; +- +- ret = devm_request_irq(&pdev->dev, irq, coda_irq_handler, 0, +- CODA_NAME "-video", dev); +- if (ret < 0) { +- dev_err(&pdev->dev, "failed to request irq: %d\n", ret); +- return ret; +- } +- +- /* JPEG IRQ */ +- if (dev->devtype->product == CODA_960) { +- irq = platform_get_irq_byname(pdev, "jpeg"); +- if (irq < 0) +- return irq; +- +- ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, +- coda9_jpeg_irq_handler, +- IRQF_ONESHOT, CODA_NAME "-jpeg", +- dev); +- if (ret < 0) { +- dev_err(&pdev->dev, "failed to request jpeg irq\n"); +- return ret; +- } +- } +- +- dev->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, +- NULL); +- if (IS_ERR(dev->rstc)) { +- ret = PTR_ERR(dev->rstc); +- dev_err(&pdev->dev, "failed get reset control: %d\n", ret); +- return ret; +- } +- +- /* Get IRAM pool from device tree */ +- pool = of_gen_pool_get(np, "iram", 0); +- if (!pool) { +- dev_err(&pdev->dev, "iram pool not available\n"); +- return -ENOMEM; +- } +- dev->iram_pool = pool; +- +- /* Get vdoa_data if supported by the platform */ +- dev->vdoa = coda_get_vdoa_data(); +- if (PTR_ERR(dev->vdoa) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- +- ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); +- if (ret) +- return ret; +- +- ratelimit_default_init(&dev->mb_err_rs); +- mutex_init(&dev->dev_mutex); +- mutex_init(&dev->coda_mutex); +- ida_init(&dev->ida); +- +- dev->debugfs_root = debugfs_create_dir("coda", NULL); +- +- /* allocate auxiliary per-device buffers for the BIT processor */ +- if (dev->devtype->product == CODA_DX6) { +- ret = coda_alloc_aux_buf(dev, &dev->workbuf, +- dev->devtype->workbuf_size, "workbuf", +- dev->debugfs_root); +- if (ret < 0) +- goto err_v4l2_register; +- } +- +- if (dev->devtype->tempbuf_size) { +- ret = coda_alloc_aux_buf(dev, &dev->tempbuf, +- dev->devtype->tempbuf_size, "tempbuf", +- dev->debugfs_root); +- if (ret < 0) +- goto err_v4l2_register; +- } +- +- dev->iram.size = dev->devtype->iram_size; +- dev->iram.vaddr = gen_pool_dma_alloc(dev->iram_pool, dev->iram.size, +- &dev->iram.paddr); +- if (!dev->iram.vaddr) { +- dev_warn(&pdev->dev, "unable to alloc iram\n"); +- } else { +- memset(dev->iram.vaddr, 0, dev->iram.size); +- dev->iram.blob.data = dev->iram.vaddr; +- dev->iram.blob.size = dev->iram.size; +- dev->iram.dentry = debugfs_create_blob("iram", 0444, +- dev->debugfs_root, +- &dev->iram.blob); +- } +- +- dev->workqueue = alloc_ordered_workqueue("coda", WQ_MEM_RECLAIM); +- if (!dev->workqueue) { +- dev_err(&pdev->dev, "unable to alloc workqueue\n"); +- ret = -ENOMEM; +- goto err_v4l2_register; +- } +- +- platform_set_drvdata(pdev, dev); +- +- /* +- * Start activated so we can directly call coda_hw_init in +- * coda_fw_callback regardless of whether CONFIG_PM is +- * enabled or whether the device is associated with a PM domain. +- */ +- pm_runtime_get_noresume(&pdev->dev); +- pm_runtime_set_active(&pdev->dev); +- pm_runtime_enable(&pdev->dev); +- +- ret = coda_firmware_request(dev); +- if (ret) +- goto err_alloc_workqueue; +- return 0; +- +-err_alloc_workqueue: +- pm_runtime_disable(&pdev->dev); +- pm_runtime_put_noidle(&pdev->dev); +- destroy_workqueue(dev->workqueue); +-err_v4l2_register: +- v4l2_device_unregister(&dev->v4l2_dev); +- return ret; +-} +- +-static void coda_remove(struct platform_device *pdev) +-{ +- struct coda_dev *dev = platform_get_drvdata(pdev); +- int i; +- +- for (i = 0; i < ARRAY_SIZE(dev->vfd); i++) { +- if (video_get_drvdata(&dev->vfd[i])) +- video_unregister_device(&dev->vfd[i]); +- } +- if (dev->m2m_dev) +- v4l2_m2m_release(dev->m2m_dev); +- pm_runtime_disable(&pdev->dev); +- v4l2_device_unregister(&dev->v4l2_dev); +- destroy_workqueue(dev->workqueue); +- if (dev->iram.vaddr) +- gen_pool_free(dev->iram_pool, (unsigned long)dev->iram.vaddr, +- dev->iram.size); +- coda_free_aux_buf(dev, &dev->codebuf); +- coda_free_aux_buf(dev, &dev->tempbuf); +- coda_free_aux_buf(dev, &dev->workbuf); +- debugfs_remove_recursive(dev->debugfs_root); +- ida_destroy(&dev->ida); +-} +- +-#ifdef CONFIG_PM +-static int coda_runtime_resume(struct device *dev) +-{ +- struct coda_dev *cdev = dev_get_drvdata(dev); +- int ret = 0; +- +- if (dev->pm_domain && cdev->codebuf.vaddr) { +- ret = coda_hw_init(cdev); +- if (ret) +- v4l2_err(&cdev->v4l2_dev, "HW initialization failed\n"); +- } +- +- return ret; +-} +-#endif +- +-static const struct dev_pm_ops coda_pm_ops = { +- SET_RUNTIME_PM_OPS(NULL, coda_runtime_resume, NULL) +-}; +- +-static struct platform_driver coda_driver = { +- .probe = coda_probe, +- .remove_new = coda_remove, +- .driver = { +- .name = CODA_NAME, +- .of_match_table = coda_dt_ids, +- .pm = &coda_pm_ops, +- }, +-}; +- +-module_platform_driver(coda_driver); +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Javier Martin "); +-MODULE_DESCRIPTION("Coda multi-standard codec V4L2 driver"); +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-gdi.c b/drivers/media/platform/chips-media/coda-gdi.c +--- a/drivers/media/platform/chips-media/coda-gdi.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda-gdi.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,146 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Coda multi-standard codec IP +- * +- * Copyright (C) 2014 Philipp Zabel, Pengutronix +- */ +- +-#include +-#include "coda.h" +- +-#define XY2_INVERT BIT(7) +-#define XY2_ZERO BIT(6) +-#define XY2_TB_XOR BIT(5) +-#define XY2_XYSEL BIT(4) +-#define XY2_Y (1 << 4) +-#define XY2_X (0 << 4) +- +-#define XY2(luma_sel, luma_bit, chroma_sel, chroma_bit) \ +- (((XY2_##luma_sel) | (luma_bit)) << 8 | \ +- (XY2_##chroma_sel) | (chroma_bit)) +- +-static const u16 xy2ca_zero_map[16] = { +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +-}; +- +-static const u16 xy2ca_tiled_map[16] = { +- XY2(Y, 0, Y, 0), +- XY2(Y, 1, Y, 1), +- XY2(Y, 2, Y, 2), +- XY2(Y, 3, X, 3), +- XY2(X, 3, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +- XY2(ZERO, 0, ZERO, 0), +-}; +- +-/* +- * RA[15:0], CA[15:8] are hardwired to contain the 24-bit macroblock +- * start offset (macroblock size is 16x16 for luma, 16x8 for chroma). +- * Bits CA[4:0] are set using XY2CA above. BA[3:0] seems to be unused. +- */ +- +-#define RBC_CA (0 << 4) +-#define RBC_BA (1 << 4) +-#define RBC_RA (2 << 4) +-#define RBC_ZERO (3 << 4) +- +-#define RBC(luma_sel, luma_bit, chroma_sel, chroma_bit) \ +- (((RBC_##luma_sel) | (luma_bit)) << 6 | \ +- (RBC_##chroma_sel) | (chroma_bit)) +- +-static const u16 rbc2axi_tiled_map[32] = { +- RBC(ZERO, 0, ZERO, 0), +- RBC(ZERO, 0, ZERO, 0), +- RBC(ZERO, 0, ZERO, 0), +- RBC(CA, 0, CA, 0), +- RBC(CA, 1, CA, 1), +- RBC(CA, 2, CA, 2), +- RBC(CA, 3, CA, 3), +- RBC(CA, 4, CA, 8), +- RBC(CA, 8, CA, 9), +- RBC(CA, 9, CA, 10), +- RBC(CA, 10, CA, 11), +- RBC(CA, 11, CA, 12), +- RBC(CA, 12, CA, 13), +- RBC(CA, 13, CA, 14), +- RBC(CA, 14, CA, 15), +- RBC(CA, 15, RA, 0), +- RBC(RA, 0, RA, 1), +- RBC(RA, 1, RA, 2), +- RBC(RA, 2, RA, 3), +- RBC(RA, 3, RA, 4), +- RBC(RA, 4, RA, 5), +- RBC(RA, 5, RA, 6), +- RBC(RA, 6, RA, 7), +- RBC(RA, 7, RA, 8), +- RBC(RA, 8, RA, 9), +- RBC(RA, 9, RA, 10), +- RBC(RA, 10, RA, 11), +- RBC(RA, 11, RA, 12), +- RBC(RA, 12, RA, 13), +- RBC(RA, 13, RA, 14), +- RBC(RA, 14, RA, 15), +- RBC(RA, 15, ZERO, 0), +-}; +- +-void coda_set_gdi_regs(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- const u16 *xy2ca_map; +- u32 xy2rbc_config; +- int i; +- +- switch (ctx->tiled_map_type) { +- case GDI_LINEAR_FRAME_MAP: +- default: +- xy2ca_map = xy2ca_zero_map; +- xy2rbc_config = 0; +- break; +- case GDI_TILED_FRAME_MB_RASTER_MAP: +- xy2ca_map = xy2ca_tiled_map; +- xy2rbc_config = CODA9_XY2RBC_TILED_MAP | +- CODA9_XY2RBC_CA_INC_HOR | +- (16 - 1) << 12 | (8 - 1) << 4; +- break; +- } +- +- for (i = 0; i < 16; i++) +- coda_write(dev, xy2ca_map[i], +- CODA9_GDI_XY2_CAS_0 + 4 * i); +- for (i = 0; i < 4; i++) +- coda_write(dev, XY2(ZERO, 0, ZERO, 0), +- CODA9_GDI_XY2_BA_0 + 4 * i); +- for (i = 0; i < 16; i++) +- coda_write(dev, XY2(ZERO, 0, ZERO, 0), +- CODA9_GDI_XY2_RAS_0 + 4 * i); +- coda_write(dev, xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG); +- if (xy2rbc_config) { +- for (i = 0; i < 32; i++) +- coda_write(dev, rbc2axi_tiled_map[i], +- CODA9_GDI_RBC2_AXI_0 + 4 * i); +- } +-} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda.h b/drivers/media/platform/chips-media/coda.h +--- a/drivers/media/platform/chips-media/coda.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda.h 1969-12-31 19:00:00.000000000 -0500 +@@ -1,403 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-or-later */ +-/* +- * Coda multi-standard codec IP +- * +- * Copyright (C) 2012 Vista Silicon S.L. +- * Javier Martin, +- * Xavier Duret +- * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix +- */ +- +-#ifndef __CODA_H__ +-#define __CODA_H__ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#include "coda_regs.h" +- +-#define CODA_MAX_FRAMEBUFFERS 19 +-#define FMO_SLICE_SAVE_BUF_SIZE (32) +- +-/* +- * This control allows applications to read the per-stream +- * (i.e. per-context) Macroblocks Error Count. This value +- * is CODA specific. +- */ +-#define V4L2_CID_CODA_MB_ERR_CNT (V4L2_CID_USER_CODA_BASE + 0) +- +-enum { +- V4L2_M2M_SRC = 0, +- V4L2_M2M_DST = 1, +-}; +- +-enum coda_inst_type { +- CODA_INST_ENCODER, +- CODA_INST_DECODER, +-}; +- +-enum coda_product { +- CODA_DX6 = 0xf001, +- CODA_HX4 = 0xf00a, +- CODA_7541 = 0xf012, +- CODA_960 = 0xf020, +-}; +- +-struct coda_video_device; +- +-struct coda_devtype { +- char *firmware[3]; +- enum coda_product product; +- const struct coda_codec *codecs; +- unsigned int num_codecs; +- const struct coda_video_device **vdevs; +- unsigned int num_vdevs; +- size_t workbuf_size; +- size_t tempbuf_size; +- size_t iram_size; +-}; +- +-struct coda_aux_buf { +- void *vaddr; +- dma_addr_t paddr; +- u32 size; +- struct debugfs_blob_wrapper blob; +- struct dentry *dentry; +-}; +- +-struct coda_dev { +- struct v4l2_device v4l2_dev; +- struct video_device vfd[6]; +- struct device *dev; +- const struct coda_devtype *devtype; +- int firmware; +- struct vdoa_data *vdoa; +- +- void __iomem *regs_base; +- struct clk *clk_per; +- struct clk *clk_ahb; +- struct reset_control *rstc; +- +- struct coda_aux_buf codebuf; +- struct coda_aux_buf tempbuf; +- struct coda_aux_buf workbuf; +- struct gen_pool *iram_pool; +- struct coda_aux_buf iram; +- +- struct mutex dev_mutex; +- struct mutex coda_mutex; +- struct workqueue_struct *workqueue; +- struct v4l2_m2m_dev *m2m_dev; +- struct ida ida; +- struct dentry *debugfs_root; +- struct ratelimit_state mb_err_rs; +-}; +- +-struct coda_codec { +- u32 mode; +- u32 src_fourcc; +- u32 dst_fourcc; +- u32 max_w; +- u32 max_h; +-}; +- +-struct coda_huff_tab; +- +-struct coda_params { +- u8 rot_mode; +- u8 h264_intra_qp; +- u8 h264_inter_qp; +- u8 h264_min_qp; +- u8 h264_max_qp; +- u8 h264_disable_deblocking_filter_idc; +- s8 h264_slice_alpha_c0_offset_div2; +- s8 h264_slice_beta_offset_div2; +- bool h264_constrained_intra_pred_flag; +- s8 h264_chroma_qp_index_offset; +- u8 h264_profile_idc; +- u8 h264_level_idc; +- u8 mpeg2_profile_idc; +- u8 mpeg2_level_idc; +- u8 mpeg4_intra_qp; +- u8 mpeg4_inter_qp; +- u8 gop_size; +- int intra_refresh; +- enum v4l2_jpeg_chroma_subsampling jpeg_chroma_subsampling; +- u8 jpeg_quality; +- u8 jpeg_restart_interval; +- u8 *jpeg_qmat_tab[3]; +- int jpeg_qmat_index[3]; +- int jpeg_huff_dc_index[3]; +- int jpeg_huff_ac_index[3]; +- u32 *jpeg_huff_data; +- struct coda_huff_tab *jpeg_huff_tab; +- int codec_mode; +- int codec_mode_aux; +- enum v4l2_mpeg_video_multi_slice_mode slice_mode; +- u32 framerate; +- u16 bitrate; +- u16 vbv_delay; +- u32 vbv_size; +- u32 slice_max_bits; +- u32 slice_max_mb; +- bool force_ipicture; +- bool gop_size_changed; +- bool bitrate_changed; +- bool framerate_changed; +- bool h264_intra_qp_changed; +- bool intra_refresh_changed; +- bool slice_mode_changed; +- bool frame_rc_enable; +- bool mb_rc_enable; +-}; +- +-struct coda_buffer_meta { +- struct list_head list; +- u32 sequence; +- struct v4l2_timecode timecode; +- u64 timestamp; +- unsigned int start; +- unsigned int end; +- bool last; +-}; +- +-/* Per-queue, driver-specific private data */ +-struct coda_q_data { +- unsigned int width; +- unsigned int height; +- unsigned int bytesperline; +- unsigned int sizeimage; +- unsigned int fourcc; +- struct v4l2_rect rect; +-}; +- +-struct coda_iram_info { +- u32 axi_sram_use; +- phys_addr_t buf_bit_use; +- phys_addr_t buf_ip_ac_dc_use; +- phys_addr_t buf_dbk_y_use; +- phys_addr_t buf_dbk_c_use; +- phys_addr_t buf_ovl_use; +- phys_addr_t buf_btp_use; +- phys_addr_t search_ram_paddr; +- int search_ram_size; +- int remaining; +- phys_addr_t next_paddr; +-}; +- +-#define GDI_LINEAR_FRAME_MAP 0 +-#define GDI_TILED_FRAME_MB_RASTER_MAP 1 +- +-struct coda_ctx; +- +-struct coda_context_ops { +- int (*queue_init)(void *priv, struct vb2_queue *src_vq, +- struct vb2_queue *dst_vq); +- int (*reqbufs)(struct coda_ctx *ctx, struct v4l2_requestbuffers *rb); +- int (*start_streaming)(struct coda_ctx *ctx); +- int (*prepare_run)(struct coda_ctx *ctx); +- void (*finish_run)(struct coda_ctx *ctx); +- void (*run_timeout)(struct coda_ctx *ctx); +- void (*seq_init_work)(struct work_struct *work); +- void (*seq_end_work)(struct work_struct *work); +- void (*release)(struct coda_ctx *ctx); +-}; +- +-struct coda_internal_frame { +- struct coda_aux_buf buf; +- struct coda_buffer_meta meta; +- u32 type; +- u32 error; +-}; +- +-struct coda_ctx { +- struct coda_dev *dev; +- struct mutex buffer_mutex; +- struct work_struct pic_run_work; +- struct work_struct seq_init_work; +- struct work_struct seq_end_work; +- struct completion completion; +- const struct coda_video_device *cvd; +- const struct coda_context_ops *ops; +- int aborting; +- int initialized; +- int streamon_out; +- int streamon_cap; +- u32 qsequence; +- u32 osequence; +- u32 sequence_offset; +- struct coda_q_data q_data[2]; +- enum coda_inst_type inst_type; +- const struct coda_codec *codec; +- enum v4l2_colorspace colorspace; +- enum v4l2_xfer_func xfer_func; +- enum v4l2_ycbcr_encoding ycbcr_enc; +- enum v4l2_quantization quantization; +- struct coda_params params; +- struct v4l2_ctrl_handler ctrls; +- struct v4l2_ctrl *h264_profile_ctrl; +- struct v4l2_ctrl *h264_level_ctrl; +- struct v4l2_ctrl *mpeg2_profile_ctrl; +- struct v4l2_ctrl *mpeg2_level_ctrl; +- struct v4l2_ctrl *mpeg4_profile_ctrl; +- struct v4l2_ctrl *mpeg4_level_ctrl; +- struct v4l2_ctrl *mb_err_cnt_ctrl; +- struct v4l2_fh fh; +- int gopcounter; +- int runcounter; +- int jpeg_ecs_offset; +- char vpu_header[3][64]; +- int vpu_header_size[3]; +- struct kfifo bitstream_fifo; +- struct mutex bitstream_mutex; +- struct coda_aux_buf bitstream; +- bool hold; +- struct coda_aux_buf parabuf; +- struct coda_aux_buf psbuf; +- struct coda_aux_buf slicebuf; +- struct coda_internal_frame internal_frames[CODA_MAX_FRAMEBUFFERS]; +- struct list_head buffer_meta_list; +- spinlock_t buffer_meta_lock; +- int num_metas; +- unsigned int first_frame_sequence; +- struct coda_aux_buf workbuf; +- int num_internal_frames; +- int idx; +- int reg_idx; +- struct coda_iram_info iram_info; +- int tiled_map_type; +- u32 bit_stream_param; +- u32 frm_dis_flg; +- u32 frame_mem_ctrl; +- u32 para_change; +- int display_idx; +- struct dentry *debugfs_entry; +- bool use_bit; +- bool use_vdoa; +- struct vdoa_ctx *vdoa; +- /* +- * wakeup mutex used to serialize encoder stop command and finish_run, +- * ensures that finish_run always either flags the last returned buffer +- * or wakes up the capture queue to signal EOS afterwards. +- */ +- struct mutex wakeup_mutex; +-}; +- +-extern int coda_debug; +- +-#define coda_dbg(level, ctx, fmt, arg...) \ +- do { \ +- if (coda_debug >= (level)) \ +- v4l2_dbg((level), coda_debug, &(ctx)->dev->v4l2_dev, \ +- "%u: " fmt, (ctx)->idx, ##arg); \ +- } while (0) +- +-void coda_write(struct coda_dev *dev, u32 data, u32 reg); +-unsigned int coda_read(struct coda_dev *dev, u32 reg); +-void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data, +- struct vb2_v4l2_buffer *buf, unsigned int reg_y); +- +-int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf, +- size_t size, const char *name, struct dentry *parent); +-void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf); +- +-int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq, +- struct vb2_queue *dst_vq); +-int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq, +- struct vb2_queue *dst_vq); +- +-int coda_hw_reset(struct coda_ctx *ctx); +- +-void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list); +- +-void coda_set_gdi_regs(struct coda_ctx *ctx); +- +-static inline struct coda_q_data *get_q_data(struct coda_ctx *ctx, +- enum v4l2_buf_type type) +-{ +- switch (type) { +- case V4L2_BUF_TYPE_VIDEO_OUTPUT: +- return &(ctx->q_data[V4L2_M2M_SRC]); +- case V4L2_BUF_TYPE_VIDEO_CAPTURE: +- return &(ctx->q_data[V4L2_M2M_DST]); +- default: +- return NULL; +- } +-} +- +-const char *coda_product_name(int product); +- +-int coda_check_firmware(struct coda_dev *dev); +- +-static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx) +-{ +- return kfifo_len(&ctx->bitstream_fifo); +-} +- +-/* +- * The bitstream prefetcher needs to read at least 2 256 byte periods past +- * the desired bitstream position for all data to reach the decoder. +- */ +-static inline bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, +- unsigned int pos) +-{ +- return (int)(ctx->bitstream_fifo.kfifo.in - ALIGN(pos, 256)) > 512; +-} +- +-bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos); +-int coda_bitstream_flush(struct coda_ctx *ctx); +- +-void coda_bit_stream_end_flag(struct coda_ctx *ctx); +- +-void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, +- enum vb2_buffer_state state); +- +-int coda_h264_filler_nal(int size, char *p); +-int coda_h264_padding(int size, char *p); +-int coda_h264_profile(int profile_idc); +-int coda_h264_level(int level_idc); +-int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb); +-int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf, +- int *size, int max_size); +- +-int coda_mpeg2_profile(int profile_idc); +-int coda_mpeg2_level(int level_idc); +-u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size); +-int coda_mpeg4_profile(int profile_idc); +-int coda_mpeg4_level(int level_idc); +-u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size); +- +-void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc, +- u8 level_idc); +- +-static inline int coda_jpeg_scale(int src, int dst) +-{ +- return (dst <= src / 8) ? 3 : +- (dst <= src / 4) ? 2 : +- (dst <= src / 2) ? 1 : 0; +-} +- +-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb); +-int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb); +-int coda_jpeg_write_tables(struct coda_ctx *ctx); +-void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality); +- +-extern const struct coda_context_ops coda_bit_encode_ops; +-extern const struct coda_context_ops coda_bit_decode_ops; +-extern const struct coda_context_ops coda9_jpeg_encode_ops; +-extern const struct coda_context_ops coda9_jpeg_decode_ops; +- +-irqreturn_t coda_irq_handler(int irq, void *data); +-irqreturn_t coda9_jpeg_irq_handler(int irq, void *data); +- +-#endif /* __CODA_H__ */ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-h264.c b/drivers/media/platform/chips-media/coda-h264.c +--- a/drivers/media/platform/chips-media/coda-h264.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda-h264.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,429 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Coda multi-standard codec IP - H.264 helper functions +- * +- * Copyright (C) 2012 Vista Silicon S.L. +- * Javier Martin, +- * Xavier Duret +- */ +- +-#include +-#include +-#include +- +-#include "coda.h" +- +-static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 }; +- +-static const u8 *coda_find_nal_header(const u8 *buf, const u8 *end) +-{ +- u32 val = 0xffffffff; +- +- do { +- val = val << 8 | *buf++; +- if (buf >= end) +- return NULL; +- } while (val != 0x00000001); +- +- return buf; +-} +- +-int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb) +-{ +- const u8 *buf = vb2_plane_vaddr(vb, 0); +- const u8 *end = buf + vb2_get_plane_payload(vb, 0); +- +- /* Find SPS header */ +- do { +- buf = coda_find_nal_header(buf, end); +- if (!buf) +- return -EINVAL; +- } while ((*buf++ & 0x1f) != 0x7); +- +- ctx->params.h264_profile_idc = buf[0]; +- ctx->params.h264_level_idc = buf[2]; +- +- return 0; +-} +- +-int coda_h264_filler_nal(int size, char *p) +-{ +- if (size < 6) +- return -EINVAL; +- +- p[0] = 0x00; +- p[1] = 0x00; +- p[2] = 0x00; +- p[3] = 0x01; +- p[4] = 0x0c; +- memset(p + 5, 0xff, size - 6); +- /* Add rbsp stop bit and trailing at the end */ +- p[size - 1] = 0x80; +- +- return 0; +-} +- +-int coda_h264_padding(int size, char *p) +-{ +- int nal_size; +- int diff; +- +- diff = size - (size & ~0x7); +- if (diff == 0) +- return 0; +- +- nal_size = coda_filler_size[diff]; +- coda_h264_filler_nal(nal_size, p); +- +- return nal_size; +-} +- +-int coda_h264_profile(int profile_idc) +-{ +- switch (profile_idc) { +- case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; +- case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN; +- case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED; +- case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; +- default: return -EINVAL; +- } +-} +- +-int coda_h264_level(int level_idc) +-{ +- switch (level_idc) { +- case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0; +- case 9: return V4L2_MPEG_VIDEO_H264_LEVEL_1B; +- case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1; +- case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2; +- case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3; +- case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0; +- case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1; +- case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2; +- case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0; +- case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1; +- case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2; +- case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0; +- case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1; +- case 42: return V4L2_MPEG_VIDEO_H264_LEVEL_4_2; +- case 50: return V4L2_MPEG_VIDEO_H264_LEVEL_5_0; +- case 51: return V4L2_MPEG_VIDEO_H264_LEVEL_5_1; +- default: return -EINVAL; +- } +-} +- +-struct rbsp { +- char *buf; +- int size; +- int pos; +-}; +- +-static inline int rbsp_read_bit(struct rbsp *rbsp) +-{ +- int shift = 7 - (rbsp->pos % 8); +- int ofs = rbsp->pos++ / 8; +- +- if (ofs >= rbsp->size) +- return -EINVAL; +- +- return (rbsp->buf[ofs] >> shift) & 1; +-} +- +-static inline int rbsp_write_bit(struct rbsp *rbsp, int bit) +-{ +- int shift = 7 - (rbsp->pos % 8); +- int ofs = rbsp->pos++ / 8; +- +- if (ofs >= rbsp->size) +- return -EINVAL; +- +- rbsp->buf[ofs] &= ~(1 << shift); +- rbsp->buf[ofs] |= bit << shift; +- +- return 0; +-} +- +-static inline int rbsp_read_bits(struct rbsp *rbsp, int num, int *val) +-{ +- int i, ret; +- int tmp = 0; +- +- if (num > 32) +- return -EINVAL; +- +- for (i = 0; i < num; i++) { +- ret = rbsp_read_bit(rbsp); +- if (ret < 0) +- return ret; +- tmp |= ret << (num - i - 1); +- } +- +- if (val) +- *val = tmp; +- +- return 0; +-} +- +-static int rbsp_write_bits(struct rbsp *rbsp, int num, int value) +-{ +- int ret; +- +- while (num--) { +- ret = rbsp_write_bit(rbsp, (value >> num) & 1); +- if (ret) +- return ret; +- } +- +- return 0; +-} +- +-static int rbsp_read_uev(struct rbsp *rbsp, unsigned int *val) +-{ +- int leading_zero_bits = 0; +- unsigned int tmp = 0; +- int ret; +- +- while ((ret = rbsp_read_bit(rbsp)) == 0) +- leading_zero_bits++; +- if (ret < 0) +- return ret; +- +- if (leading_zero_bits > 0) { +- ret = rbsp_read_bits(rbsp, leading_zero_bits, &tmp); +- if (ret) +- return ret; +- } +- +- if (val) +- *val = (1 << leading_zero_bits) - 1 + tmp; +- +- return 0; +-} +- +-static int rbsp_write_uev(struct rbsp *rbsp, unsigned int value) +-{ +- int i; +- int ret; +- int tmp = value + 1; +- int leading_zero_bits = fls(tmp) - 1; +- +- for (i = 0; i < leading_zero_bits; i++) { +- ret = rbsp_write_bit(rbsp, 0); +- if (ret) +- return ret; +- } +- +- return rbsp_write_bits(rbsp, leading_zero_bits + 1, tmp); +-} +- +-static int rbsp_read_sev(struct rbsp *rbsp, int *val) +-{ +- unsigned int tmp; +- int ret; +- +- ret = rbsp_read_uev(rbsp, &tmp); +- if (ret) +- return ret; +- +- if (val) { +- if (tmp & 1) +- *val = (tmp + 1) / 2; +- else +- *val = -(tmp / 2); +- } +- +- return 0; +-} +- +-/** +- * coda_h264_sps_fixup - fixes frame cropping values in h.264 SPS +- * @ctx: encoder context +- * @width: visible width +- * @height: visible height +- * @buf: buffer containing h.264 SPS RBSP, starting with NAL header +- * @size: modified RBSP size return value +- * @max_size: available size in buf +- * +- * Rewrites the frame cropping values in an h.264 SPS RBSP correctly for the +- * given visible width and height. +- */ +-int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf, +- int *size, int max_size) +-{ +- int profile_idc; +- unsigned int pic_order_cnt_type; +- int pic_width_in_mbs_minus1, pic_height_in_map_units_minus1; +- int frame_mbs_only_flag, frame_cropping_flag; +- int vui_parameters_present_flag; +- unsigned int crop_right, crop_bottom; +- struct rbsp sps; +- int pos; +- int ret; +- +- if (*size < 8 || *size >= max_size) +- return -EINVAL; +- +- sps.buf = buf + 5; /* Skip NAL header */ +- sps.size = *size - 5; +- +- profile_idc = sps.buf[0]; +- /* Skip constraint_set[0-5]_flag, reserved_zero_2bits */ +- /* Skip level_idc */ +- sps.pos = 24; +- +- /* seq_parameter_set_id */ +- ret = rbsp_read_uev(&sps, NULL); +- if (ret) +- return ret; +- +- if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || +- profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || +- profile_idc == 86 || profile_idc == 118 || profile_idc == 128 || +- profile_idc == 138 || profile_idc == 139 || profile_idc == 134 || +- profile_idc == 135) { +- dev_err(ctx->fh.vdev->dev_parent, +- "%s: Handling profile_idc %d not implemented\n", +- __func__, profile_idc); +- return -EINVAL; +- } +- +- /* log2_max_frame_num_minus4 */ +- ret = rbsp_read_uev(&sps, NULL); +- if (ret) +- return ret; +- +- ret = rbsp_read_uev(&sps, &pic_order_cnt_type); +- if (ret) +- return ret; +- +- if (pic_order_cnt_type == 0) { +- /* log2_max_pic_order_cnt_lsb_minus4 */ +- ret = rbsp_read_uev(&sps, NULL); +- if (ret) +- return ret; +- } else if (pic_order_cnt_type == 1) { +- unsigned int i, num_ref_frames_in_pic_order_cnt_cycle; +- +- /* delta_pic_order_always_zero_flag */ +- ret = rbsp_read_bit(&sps); +- if (ret < 0) +- return ret; +- /* offset_for_non_ref_pic */ +- ret = rbsp_read_sev(&sps, NULL); +- if (ret) +- return ret; +- /* offset_for_top_to_bottom_field */ +- ret = rbsp_read_sev(&sps, NULL); +- if (ret) +- return ret; +- +- ret = rbsp_read_uev(&sps, +- &num_ref_frames_in_pic_order_cnt_cycle); +- if (ret) +- return ret; +- for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) { +- /* offset_for_ref_frame */ +- ret = rbsp_read_sev(&sps, NULL); +- if (ret) +- return ret; +- } +- } +- +- /* max_num_ref_frames */ +- ret = rbsp_read_uev(&sps, NULL); +- if (ret) +- return ret; +- +- /* gaps_in_frame_num_value_allowed_flag */ +- ret = rbsp_read_bit(&sps); +- if (ret < 0) +- return ret; +- ret = rbsp_read_uev(&sps, &pic_width_in_mbs_minus1); +- if (ret) +- return ret; +- ret = rbsp_read_uev(&sps, &pic_height_in_map_units_minus1); +- if (ret) +- return ret; +- frame_mbs_only_flag = ret = rbsp_read_bit(&sps); +- if (ret < 0) +- return ret; +- if (!frame_mbs_only_flag) { +- /* mb_adaptive_frame_field_flag */ +- ret = rbsp_read_bit(&sps); +- if (ret < 0) +- return ret; +- } +- /* direct_8x8_inference_flag */ +- ret = rbsp_read_bit(&sps); +- if (ret < 0) +- return ret; +- +- /* Mark position of the frame cropping flag */ +- pos = sps.pos; +- frame_cropping_flag = ret = rbsp_read_bit(&sps); +- if (ret < 0) +- return ret; +- if (frame_cropping_flag) { +- unsigned int crop_left, crop_top; +- +- ret = rbsp_read_uev(&sps, &crop_left); +- if (ret) +- return ret; +- ret = rbsp_read_uev(&sps, &crop_right); +- if (ret) +- return ret; +- ret = rbsp_read_uev(&sps, &crop_top); +- if (ret) +- return ret; +- ret = rbsp_read_uev(&sps, &crop_bottom); +- if (ret) +- return ret; +- } +- vui_parameters_present_flag = ret = rbsp_read_bit(&sps); +- if (ret < 0) +- return ret; +- if (vui_parameters_present_flag) { +- dev_err(ctx->fh.vdev->dev_parent, +- "%s: Handling vui_parameters not implemented\n", +- __func__); +- return -EINVAL; +- } +- +- crop_right = round_up(width, 16) - width; +- crop_bottom = round_up(height, 16) - height; +- crop_right /= 2; +- if (frame_mbs_only_flag) +- crop_bottom /= 2; +- else +- crop_bottom /= 4; +- +- +- sps.size = max_size - 5; +- sps.pos = pos; +- frame_cropping_flag = 1; +- ret = rbsp_write_bit(&sps, frame_cropping_flag); +- if (ret) +- return ret; +- ret = rbsp_write_uev(&sps, 0); /* crop_left */ +- if (ret) +- return ret; +- ret = rbsp_write_uev(&sps, crop_right); +- if (ret) +- return ret; +- ret = rbsp_write_uev(&sps, 0); /* crop_top */ +- if (ret) +- return ret; +- ret = rbsp_write_uev(&sps, crop_bottom); +- if (ret) +- return ret; +- ret = rbsp_write_bit(&sps, 0); /* vui_parameters_present_flag */ +- if (ret) +- return ret; +- ret = rbsp_write_bit(&sps, 1); +- if (ret) +- return ret; +- +- *size = 5 + DIV_ROUND_UP(sps.pos, 8); +- +- return 0; +-} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-jpeg.c b/drivers/media/platform/chips-media/coda-jpeg.c +--- a/drivers/media/platform/chips-media/coda-jpeg.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda-jpeg.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,1547 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Coda multi-standard codec IP - JPEG support functions +- * +- * Copyright (C) 2014 Philipp Zabel, Pengutronix +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "coda.h" +-#include "trace.h" +- +-#define SOI_MARKER 0xffd8 +-#define APP9_MARKER 0xffe9 +-#define DRI_MARKER 0xffdd +-#define DQT_MARKER 0xffdb +-#define DHT_MARKER 0xffc4 +-#define SOF_MARKER 0xffc0 +-#define SOS_MARKER 0xffda +-#define EOI_MARKER 0xffd9 +- +-enum { +- CODA9_JPEG_FORMAT_420, +- CODA9_JPEG_FORMAT_422, +- CODA9_JPEG_FORMAT_224, +- CODA9_JPEG_FORMAT_444, +- CODA9_JPEG_FORMAT_400, +-}; +- +-struct coda_huff_tab { +- u8 luma_dc[16 + 12]; +- u8 chroma_dc[16 + 12]; +- u8 luma_ac[16 + 162]; +- u8 chroma_ac[16 + 162]; +- +- /* DC Luma, DC Chroma, AC Luma, AC Chroma */ +- s16 min[4 * 16]; +- s16 max[4 * 16]; +- s8 ptr[4 * 16]; +-}; +- +-#define CODA9_JPEG_ENC_HUFF_DATA_SIZE (256 + 256 + 16 + 16) +- +-/* +- * Typical Huffman tables for 8-bit precision luminance and +- * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3 +- */ +- +-static const unsigned char luma_dc[16 + 12] = { +- /* bits */ +- 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, +- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- /* values */ +- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +- 0x08, 0x09, 0x0a, 0x0b, +-}; +- +-static const unsigned char chroma_dc[16 + 12] = { +- /* bits */ +- 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, +- 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +- /* values */ +- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +- 0x08, 0x09, 0x0a, 0x0b, +-}; +- +-static const unsigned char luma_ac[16 + 162 + 2] = { +- /* bits */ +- 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, +- 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, +- /* values */ +- 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, +- 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, +- 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, +- 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, +- 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, +- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, +- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, +- 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, +- 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, +- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, +- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, +- 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, +- 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, +- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, +- 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, +- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, +- 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, +- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, +- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, +- 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, +- 0xf9, 0xfa, /* padded to 32-bit */ +-}; +- +-static const unsigned char chroma_ac[16 + 162 + 2] = { +- /* bits */ +- 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, +- 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, +- /* values */ +- 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, +- 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, +- 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, +- 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, +- 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, +- 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, +- 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, +- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, +- 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, +- 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, +- 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, +- 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, +- 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, +- 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, +- 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, +- 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, +- 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, +- 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, +- 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, +- 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, +- 0xf9, 0xfa, /* padded to 32-bit */ +-}; +- +-/* +- * Quantization tables for luminance and chrominance components in +- * zig-zag scan order from the Freescale i.MX VPU libraries +- */ +- +-static unsigned char luma_q[64] = { +- 0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05, +- 0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b, +- 0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a, +- 0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, +-}; +- +-static unsigned char chroma_q[64] = { +- 0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10, +- 0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14, +- 0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, +- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, +-}; +- +-static const unsigned char width_align[] = { +- [CODA9_JPEG_FORMAT_420] = 16, +- [CODA9_JPEG_FORMAT_422] = 16, +- [CODA9_JPEG_FORMAT_224] = 8, +- [CODA9_JPEG_FORMAT_444] = 8, +- [CODA9_JPEG_FORMAT_400] = 8, +-}; +- +-static const unsigned char height_align[] = { +- [CODA9_JPEG_FORMAT_420] = 16, +- [CODA9_JPEG_FORMAT_422] = 8, +- [CODA9_JPEG_FORMAT_224] = 16, +- [CODA9_JPEG_FORMAT_444] = 8, +- [CODA9_JPEG_FORMAT_400] = 8, +-}; +- +-static int coda9_jpeg_chroma_format(u32 pixfmt) +-{ +- switch (pixfmt) { +- case V4L2_PIX_FMT_YUV420: +- case V4L2_PIX_FMT_NV12: +- return CODA9_JPEG_FORMAT_420; +- case V4L2_PIX_FMT_YUV422P: +- return CODA9_JPEG_FORMAT_422; +- case V4L2_PIX_FMT_YUV444: +- return CODA9_JPEG_FORMAT_444; +- case V4L2_PIX_FMT_GREY: +- return CODA9_JPEG_FORMAT_400; +- } +- return -EINVAL; +-} +- +-struct coda_memcpy_desc { +- int offset; +- const void *src; +- size_t len; +-}; +- +-static void coda_memcpy_parabuf(void *parabuf, +- const struct coda_memcpy_desc *desc) +-{ +- u32 *dst = parabuf + desc->offset; +- const u32 *src = desc->src; +- int len = desc->len / 4; +- int i; +- +- for (i = 0; i < len; i += 2) { +- dst[i + 1] = swab32(src[i]); +- dst[i] = swab32(src[i + 1]); +- } +-} +- +-int coda_jpeg_write_tables(struct coda_ctx *ctx) +-{ +- int i; +- static const struct coda_memcpy_desc huff[8] = { +- { 0, luma_dc, sizeof(luma_dc) }, +- { 32, luma_ac, sizeof(luma_ac) }, +- { 216, chroma_dc, sizeof(chroma_dc) }, +- { 248, chroma_ac, sizeof(chroma_ac) }, +- }; +- struct coda_memcpy_desc qmat[3] = { +- { 512, ctx->params.jpeg_qmat_tab[0], 64 }, +- { 576, ctx->params.jpeg_qmat_tab[1], 64 }, +- { 640, ctx->params.jpeg_qmat_tab[1], 64 }, +- }; +- +- /* Write huffman tables to parameter memory */ +- for (i = 0; i < ARRAY_SIZE(huff); i++) +- coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i); +- +- /* Write Q-matrix to parameter memory */ +- for (i = 0; i < ARRAY_SIZE(qmat); i++) +- coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i); +- +- return 0; +-} +- +-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb) +-{ +- void *vaddr = vb2_plane_vaddr(vb, 0); +- u16 soi, eoi; +- int len, i; +- +- soi = be16_to_cpup((__be16 *)vaddr); +- if (soi != SOI_MARKER) +- return false; +- +- len = vb2_get_plane_payload(vb, 0); +- vaddr += len - 2; +- for (i = 0; i < 32; i++) { +- eoi = be16_to_cpup((__be16 *)(vaddr - i)); +- if (eoi == EOI_MARKER) { +- if (i > 0) +- vb2_set_plane_payload(vb, 0, len - i); +- return true; +- } +- } +- +- return false; +-} +- +-static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num); +- +-int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb) +-{ +- struct coda_dev *dev = ctx->dev; +- u8 *buf = vb2_plane_vaddr(vb, 0); +- size_t len = vb2_get_plane_payload(vb, 0); +- struct v4l2_jpeg_scan_header scan_header; +- struct v4l2_jpeg_reference quantization_tables[4] = { }; +- struct v4l2_jpeg_reference huffman_tables[4] = { }; +- struct v4l2_jpeg_header header = { +- .scan = &scan_header, +- .quantization_tables = quantization_tables, +- .huffman_tables = huffman_tables, +- }; +- struct coda_q_data *q_data_src; +- struct coda_huff_tab *huff_tab; +- int i, j, ret; +- +- ret = v4l2_jpeg_parse_header(buf, len, &header); +- if (ret < 0) { +- v4l2_err(&dev->v4l2_dev, "failed to parse JPEG header: %pe\n", +- ERR_PTR(ret)); +- return ret; +- } +- +- ctx->params.jpeg_restart_interval = header.restart_interval; +- +- /* check frame header */ +- if (header.frame.height > ctx->codec->max_h || +- header.frame.width > ctx->codec->max_w) { +- v4l2_err(&dev->v4l2_dev, "invalid dimensions: %dx%d\n", +- header.frame.width, header.frame.height); +- return -EINVAL; +- } +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- if (header.frame.height != q_data_src->height || +- header.frame.width != q_data_src->width) { +- v4l2_err(&dev->v4l2_dev, +- "dimensions don't match format: %dx%d\n", +- header.frame.width, header.frame.height); +- return -EINVAL; +- } +- +- if (header.frame.num_components != 3) { +- v4l2_err(&dev->v4l2_dev, +- "unsupported number of components: %d\n", +- header.frame.num_components); +- return -EINVAL; +- } +- +- /* install quantization tables */ +- if (quantization_tables[3].start) { +- v4l2_err(&dev->v4l2_dev, +- "only 3 quantization tables supported\n"); +- return -EINVAL; +- } +- for (i = 0; i < 3; i++) { +- if (!quantization_tables[i].start) +- continue; +- if (quantization_tables[i].length != 64) { +- v4l2_err(&dev->v4l2_dev, +- "only 8-bit quantization tables supported\n"); +- continue; +- } +- if (!ctx->params.jpeg_qmat_tab[i]) { +- ctx->params.jpeg_qmat_tab[i] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[i]) +- return -ENOMEM; +- } +- memcpy(ctx->params.jpeg_qmat_tab[i], +- quantization_tables[i].start, 64); +- } +- +- /* install Huffman tables */ +- for (i = 0; i < 4; i++) { +- if (!huffman_tables[i].start) { +- v4l2_err(&dev->v4l2_dev, "missing Huffman table\n"); +- return -EINVAL; +- } +- /* AC tables should be between 17 -> 178, DC between 17 -> 28 */ +- if (huffman_tables[i].length < 17 || +- huffman_tables[i].length > 178 || +- ((i & 2) == 0 && huffman_tables[i].length > 28)) { +- v4l2_err(&dev->v4l2_dev, +- "invalid Huffman table %d length: %zu\n", +- i, huffman_tables[i].length); +- return -EINVAL; +- } +- } +- huff_tab = ctx->params.jpeg_huff_tab; +- if (!huff_tab) { +- huff_tab = kzalloc(sizeof(struct coda_huff_tab), GFP_KERNEL); +- if (!huff_tab) +- return -ENOMEM; +- ctx->params.jpeg_huff_tab = huff_tab; +- } +- +- memset(huff_tab, 0, sizeof(*huff_tab)); +- memcpy(huff_tab->luma_dc, huffman_tables[0].start, huffman_tables[0].length); +- memcpy(huff_tab->chroma_dc, huffman_tables[1].start, huffman_tables[1].length); +- memcpy(huff_tab->luma_ac, huffman_tables[2].start, huffman_tables[2].length); +- memcpy(huff_tab->chroma_ac, huffman_tables[3].start, huffman_tables[3].length); +- +- /* check scan header */ +- for (i = 0; i < scan_header.num_components; i++) { +- struct v4l2_jpeg_scan_component_spec *scan_component; +- +- scan_component = &scan_header.component[i]; +- for (j = 0; j < header.frame.num_components; j++) { +- if (header.frame.component[j].component_identifier == +- scan_component->component_selector) +- break; +- } +- if (j == header.frame.num_components) +- continue; +- +- ctx->params.jpeg_huff_dc_index[j] = +- scan_component->dc_entropy_coding_table_selector; +- ctx->params.jpeg_huff_ac_index[j] = +- scan_component->ac_entropy_coding_table_selector; +- } +- +- /* Generate Huffman table information */ +- for (i = 0; i < 4; i++) +- coda9_jpeg_gen_dec_huff_tab(ctx, i); +- +- /* start of entropy coded segment */ +- ctx->jpeg_ecs_offset = header.ecs_offset; +- +- switch (header.frame.subsampling) { +- case V4L2_JPEG_CHROMA_SUBSAMPLING_420: +- case V4L2_JPEG_CHROMA_SUBSAMPLING_422: +- ctx->params.jpeg_chroma_subsampling = header.frame.subsampling; +- break; +- default: +- v4l2_err(&dev->v4l2_dev, "chroma subsampling not supported: %d", +- header.frame.subsampling); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static inline void coda9_jpeg_write_huff_values(struct coda_dev *dev, u8 *bits, +- int num_values) +-{ +- s8 *values = (s8 *)(bits + 16); +- int huff_length, i; +- +- for (huff_length = 0, i = 0; i < 16; i++) +- huff_length += bits[i]; +- for (i = huff_length; i < num_values; i++) +- values[i] = -1; +- for (i = 0; i < num_values; i++) +- coda_write(dev, (s32)values[i], CODA9_REG_JPEG_HUFF_DATA); +-} +- +-static void coda9_jpeg_dec_huff_setup(struct coda_ctx *ctx) +-{ +- struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab; +- struct coda_dev *dev = ctx->dev; +- s16 *huff_min = huff_tab->min; +- s16 *huff_max = huff_tab->max; +- s8 *huff_ptr = huff_tab->ptr; +- int i; +- +- /* MIN Tables */ +- coda_write(dev, 0x003, CODA9_REG_JPEG_HUFF_CTRL); +- coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_ADDR); +- for (i = 0; i < 4 * 16; i++) +- coda_write(dev, (s32)huff_min[i], CODA9_REG_JPEG_HUFF_DATA); +- +- /* MAX Tables */ +- coda_write(dev, 0x403, CODA9_REG_JPEG_HUFF_CTRL); +- coda_write(dev, 0x440, CODA9_REG_JPEG_HUFF_ADDR); +- for (i = 0; i < 4 * 16; i++) +- coda_write(dev, (s32)huff_max[i], CODA9_REG_JPEG_HUFF_DATA); +- +- /* PTR Tables */ +- coda_write(dev, 0x803, CODA9_REG_JPEG_HUFF_CTRL); +- coda_write(dev, 0x880, CODA9_REG_JPEG_HUFF_ADDR); +- for (i = 0; i < 4 * 16; i++) +- coda_write(dev, (s32)huff_ptr[i], CODA9_REG_JPEG_HUFF_DATA); +- +- /* VAL Tables: DC Luma, DC Chroma, AC Luma, AC Chroma */ +- coda_write(dev, 0xc03, CODA9_REG_JPEG_HUFF_CTRL); +- coda9_jpeg_write_huff_values(dev, huff_tab->luma_dc, 12); +- coda9_jpeg_write_huff_values(dev, huff_tab->chroma_dc, 12); +- coda9_jpeg_write_huff_values(dev, huff_tab->luma_ac, 162); +- coda9_jpeg_write_huff_values(dev, huff_tab->chroma_ac, 162); +- coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_CTRL); +-} +- +-static inline void coda9_jpeg_write_qmat_tab(struct coda_dev *dev, +- u8 *qmat, int index) +-{ +- int i; +- +- coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL); +- for (i = 0; i < 64; i++) +- coda_write(dev, qmat[i], CODA9_REG_JPEG_QMAT_DATA); +- coda_write(dev, 0, CODA9_REG_JPEG_QMAT_CTRL); +-} +- +-static void coda9_jpeg_qmat_setup(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- int *qmat_index = ctx->params.jpeg_qmat_index; +- u8 **qmat_tab = ctx->params.jpeg_qmat_tab; +- +- coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[0]], 0x00); +- coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[1]], 0x40); +- coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[2]], 0x80); +-} +- +-static void coda9_jpeg_dec_bbc_gbu_setup(struct coda_ctx *ctx, +- struct vb2_buffer *buf, u32 ecs_offset) +-{ +- struct coda_dev *dev = ctx->dev; +- int page_ptr, word_ptr, bit_ptr; +- u32 bbc_base_addr, end_addr; +- int bbc_cur_pos; +- int ret, val; +- +- bbc_base_addr = vb2_dma_contig_plane_dma_addr(buf, 0); +- end_addr = bbc_base_addr + vb2_get_plane_payload(buf, 0); +- +- page_ptr = ecs_offset / 256; +- word_ptr = (ecs_offset % 256) / 4; +- if (page_ptr & 1) +- word_ptr += 64; +- bit_ptr = (ecs_offset % 4) * 8; +- if (word_ptr & 1) +- bit_ptr += 32; +- word_ptr &= ~0x1; +- +- coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_WR_PTR); +- coda_write(dev, bbc_base_addr, CODA9_REG_JPEG_BBC_BAS_ADDR); +- +- /* Leave 3 256-byte page margin to avoid a BBC interrupt */ +- coda_write(dev, end_addr + 256 * 3 + 256, CODA9_REG_JPEG_BBC_END_ADDR); +- val = DIV_ROUND_UP(vb2_plane_size(buf, 0), 256) + 3; +- coda_write(dev, BIT(31) | val, CODA9_REG_JPEG_BBC_STRM_CTRL); +- +- bbc_cur_pos = page_ptr; +- coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); +- coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8), +- CODA9_REG_JPEG_BBC_EXT_ADDR); +- coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR); +- coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); +- coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND); +- do { +- ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY); +- } while (ret == 1); +- +- bbc_cur_pos++; +- coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); +- coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8), +- CODA9_REG_JPEG_BBC_EXT_ADDR); +- coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR); +- coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); +- coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND); +- do { +- ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY); +- } while (ret == 1); +- +- bbc_cur_pos++; +- coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS); +- coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL); +- +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_TT_CNT); +- coda_write(dev, word_ptr, CODA9_REG_JPEG_GBU_WD_PTR); +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); +- coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); +- if (page_ptr & 1) { +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBIR); +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBHR); +- } else { +- coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR); +- coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR); +- } +- coda_write(dev, 4, CODA9_REG_JPEG_GBU_CTRL); +- coda_write(dev, bit_ptr, CODA9_REG_JPEG_GBU_FF_RPTR); +- coda_write(dev, 3, CODA9_REG_JPEG_GBU_CTRL); +-} +- +-static const int bus_req_num[] = { +- [CODA9_JPEG_FORMAT_420] = 2, +- [CODA9_JPEG_FORMAT_422] = 3, +- [CODA9_JPEG_FORMAT_224] = 3, +- [CODA9_JPEG_FORMAT_444] = 4, +- [CODA9_JPEG_FORMAT_400] = 4, +-}; +- +-#define MCU_INFO(mcu_block_num, comp_num, comp0_info, comp1_info, comp2_info) \ +- (((mcu_block_num) << CODA9_JPEG_MCU_BLOCK_NUM_OFFSET) | \ +- ((comp_num) << CODA9_JPEG_COMP_NUM_OFFSET) | \ +- ((comp0_info) << CODA9_JPEG_COMP0_INFO_OFFSET) | \ +- ((comp1_info) << CODA9_JPEG_COMP1_INFO_OFFSET) | \ +- ((comp2_info) << CODA9_JPEG_COMP2_INFO_OFFSET)) +- +-static const u32 mcu_info[] = { +- [CODA9_JPEG_FORMAT_420] = MCU_INFO(6, 3, 10, 5, 5), +- [CODA9_JPEG_FORMAT_422] = MCU_INFO(4, 3, 9, 5, 5), +- [CODA9_JPEG_FORMAT_224] = MCU_INFO(4, 3, 6, 5, 5), +- [CODA9_JPEG_FORMAT_444] = MCU_INFO(3, 3, 5, 5, 5), +- [CODA9_JPEG_FORMAT_400] = MCU_INFO(1, 1, 5, 0, 0), +-}; +- +-/* +- * Convert Huffman table specifcations to tables of codes and code lengths. +- * For reference, see JPEG ITU-T.81 (ISO/IEC 10918-1) [1] +- * +- * [1] https://www.w3.org/Graphics/JPEG/itu-t81.pdf +- */ +-static int coda9_jpeg_gen_enc_huff_tab(struct coda_ctx *ctx, int tab_num, +- int *ehufsi, int *ehufco) +-{ +- int i, j, k, lastk, si, code, maxsymbol; +- const u8 *bits, *huffval; +- struct { +- int size[256]; +- int code[256]; +- } *huff; +- static const unsigned char *huff_tabs[4] = { +- luma_dc, luma_ac, chroma_dc, chroma_ac, +- }; +- int ret = -EINVAL; +- +- huff = kzalloc(sizeof(*huff), GFP_KERNEL); +- if (!huff) +- return -ENOMEM; +- +- bits = huff_tabs[tab_num]; +- huffval = huff_tabs[tab_num] + 16; +- +- maxsymbol = tab_num & 1 ? 256 : 16; +- +- /* Figure C.1 - Generation of table of Huffman code sizes */ +- k = 0; +- for (i = 1; i <= 16; i++) { +- j = bits[i - 1]; +- if (k + j > maxsymbol) +- goto out; +- while (j--) +- huff->size[k++] = i; +- } +- lastk = k; +- +- /* Figure C.2 - Generation of table of Huffman codes */ +- k = 0; +- code = 0; +- si = huff->size[0]; +- while (k < lastk) { +- while (huff->size[k] == si) { +- huff->code[k++] = code; +- code++; +- } +- if (code >= (1 << si)) +- goto out; +- code <<= 1; +- si++; +- } +- +- /* Figure C.3 - Ordering procedure for encoding procedure code tables */ +- for (k = 0; k < lastk; k++) { +- i = huffval[k]; +- if (i >= maxsymbol || ehufsi[i]) +- goto out; +- ehufco[i] = huff->code[k]; +- ehufsi[i] = huff->size[k]; +- } +- +- ret = 0; +-out: +- kfree(huff); +- return ret; +-} +- +-#define DC_TABLE_INDEX0 0 +-#define AC_TABLE_INDEX0 1 +-#define DC_TABLE_INDEX1 2 +-#define AC_TABLE_INDEX1 3 +- +-static u8 *coda9_jpeg_get_huff_bits(struct coda_ctx *ctx, int tab_num) +-{ +- struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab; +- +- if (!huff_tab) +- return NULL; +- +- switch (tab_num) { +- case DC_TABLE_INDEX0: return huff_tab->luma_dc; +- case AC_TABLE_INDEX0: return huff_tab->luma_ac; +- case DC_TABLE_INDEX1: return huff_tab->chroma_dc; +- case AC_TABLE_INDEX1: return huff_tab->chroma_ac; +- } +- +- return NULL; +-} +- +-static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num) +-{ +- int ptr_cnt = 0, huff_code = 0, zero_flag = 0, data_flag = 0; +- u8 *huff_bits; +- s16 *huff_max; +- s16 *huff_min; +- s8 *huff_ptr; +- int ofs; +- int i; +- +- huff_bits = coda9_jpeg_get_huff_bits(ctx, tab_num); +- if (!huff_bits) +- return -EINVAL; +- +- /* DC/AC Luma, DC/AC Chroma -> DC Luma/Chroma, AC Luma/Chroma */ +- ofs = ((tab_num & 1) << 1) | ((tab_num >> 1) & 1); +- ofs *= 16; +- +- huff_ptr = ctx->params.jpeg_huff_tab->ptr + ofs; +- huff_max = ctx->params.jpeg_huff_tab->max + ofs; +- huff_min = ctx->params.jpeg_huff_tab->min + ofs; +- +- for (i = 0; i < 16; i++) { +- if (huff_bits[i]) { +- huff_ptr[i] = ptr_cnt; +- ptr_cnt += huff_bits[i]; +- huff_min[i] = huff_code; +- huff_max[i] = huff_code + (huff_bits[i] - 1); +- data_flag = 1; +- zero_flag = 0; +- } else { +- huff_ptr[i] = -1; +- huff_min[i] = -1; +- huff_max[i] = -1; +- zero_flag = 1; +- } +- +- if (data_flag == 1) { +- if (zero_flag == 1) +- huff_code <<= 1; +- else +- huff_code = (huff_max[i] + 1) << 1; +- } +- } +- +- return 0; +-} +- +-static int coda9_jpeg_load_huff_tab(struct coda_ctx *ctx) +-{ +- struct { +- int size[4][256]; +- int code[4][256]; +- } *huff; +- u32 *huff_data; +- int i, j; +- int ret; +- +- huff = kzalloc(sizeof(*huff), GFP_KERNEL); +- if (!huff) +- return -ENOMEM; +- +- /* Generate all four (luma/chroma DC/AC) code/size lookup tables */ +- for (i = 0; i < 4; i++) { +- ret = coda9_jpeg_gen_enc_huff_tab(ctx, i, huff->size[i], +- huff->code[i]); +- if (ret) +- goto out; +- } +- +- if (!ctx->params.jpeg_huff_data) { +- ctx->params.jpeg_huff_data = +- kzalloc(sizeof(u32) * CODA9_JPEG_ENC_HUFF_DATA_SIZE, +- GFP_KERNEL); +- if (!ctx->params.jpeg_huff_data) { +- ret = -ENOMEM; +- goto out; +- } +- } +- huff_data = ctx->params.jpeg_huff_data; +- +- for (j = 0; j < 4; j++) { +- /* Store Huffman lookup tables in AC0, AC1, DC0, DC1 order */ +- int t = (j == 0) ? AC_TABLE_INDEX0 : +- (j == 1) ? AC_TABLE_INDEX1 : +- (j == 2) ? DC_TABLE_INDEX0 : +- DC_TABLE_INDEX1; +- /* DC tables only have 16 entries */ +- int len = (j < 2) ? 256 : 16; +- +- for (i = 0; i < len; i++) { +- if (huff->size[t][i] == 0 && huff->code[t][i] == 0) +- *(huff_data++) = 0; +- else +- *(huff_data++) = +- ((huff->size[t][i] - 1) << 16) | +- huff->code[t][i]; +- } +- } +- +- ret = 0; +-out: +- kfree(huff); +- return ret; +-} +- +-static void coda9_jpeg_write_huff_tab(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- u32 *huff_data = ctx->params.jpeg_huff_data; +- int i; +- +- /* Write Huffman size/code lookup tables in AC0, AC1, DC0, DC1 order */ +- coda_write(dev, 0x3, CODA9_REG_JPEG_HUFF_CTRL); +- for (i = 0; i < CODA9_JPEG_ENC_HUFF_DATA_SIZE; i++) +- coda_write(dev, *(huff_data++), CODA9_REG_JPEG_HUFF_DATA); +- coda_write(dev, 0x0, CODA9_REG_JPEG_HUFF_CTRL); +-} +- +-static inline void coda9_jpeg_write_qmat_quotients(struct coda_dev *dev, +- u8 *qmat, int index) +-{ +- int i; +- +- coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL); +- for (i = 0; i < 64; i++) +- coda_write(dev, 0x80000 / qmat[i], CODA9_REG_JPEG_QMAT_DATA); +- coda_write(dev, index, CODA9_REG_JPEG_QMAT_CTRL); +-} +- +-static void coda9_jpeg_load_qmat_tab(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- u8 *luma_tab; +- u8 *chroma_tab; +- +- luma_tab = ctx->params.jpeg_qmat_tab[0]; +- if (!luma_tab) +- luma_tab = luma_q; +- +- chroma_tab = ctx->params.jpeg_qmat_tab[1]; +- if (!chroma_tab) +- chroma_tab = chroma_q; +- +- coda9_jpeg_write_qmat_quotients(dev, luma_tab, 0x00); +- coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x40); +- coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x80); +-} +- +-struct coda_jpeg_stream { +- u8 *curr; +- u8 *end; +-}; +- +-static inline int coda_jpeg_put_byte(u8 byte, struct coda_jpeg_stream *stream) +-{ +- if (stream->curr >= stream->end) +- return -EINVAL; +- +- *stream->curr++ = byte; +- +- return 0; +-} +- +-static inline int coda_jpeg_put_word(u16 word, struct coda_jpeg_stream *stream) +-{ +- if (stream->curr + sizeof(__be16) > stream->end) +- return -EINVAL; +- +- put_unaligned_be16(word, stream->curr); +- stream->curr += sizeof(__be16); +- +- return 0; +-} +- +-static int coda_jpeg_put_table(u16 marker, u8 index, const u8 *table, +- size_t len, struct coda_jpeg_stream *stream) +-{ +- int i, ret; +- +- ret = coda_jpeg_put_word(marker, stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_word(3 + len, stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_byte(index, stream); +- for (i = 0; i < len && ret == 0; i++) +- ret = coda_jpeg_put_byte(table[i], stream); +- +- return ret; +-} +- +-static int coda_jpeg_define_quantization_table(struct coda_ctx *ctx, u8 index, +- struct coda_jpeg_stream *stream) +-{ +- return coda_jpeg_put_table(DQT_MARKER, index, +- ctx->params.jpeg_qmat_tab[index], 64, +- stream); +-} +- +-static int coda_jpeg_define_huffman_table(u8 index, const u8 *table, size_t len, +- struct coda_jpeg_stream *stream) +-{ +- return coda_jpeg_put_table(DHT_MARKER, index, table, len, stream); +-} +- +-static int coda9_jpeg_encode_header(struct coda_ctx *ctx, int len, u8 *buf) +-{ +- struct coda_jpeg_stream stream = { buf, buf + len }; +- struct coda_q_data *q_data_src; +- int chroma_format, comp_num; +- int i, ret, pad; +- +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc); +- if (chroma_format < 0) +- return 0; +- +- /* Start Of Image */ +- ret = coda_jpeg_put_word(SOI_MARKER, &stream); +- if (ret < 0) +- return ret; +- +- /* Define Restart Interval */ +- if (ctx->params.jpeg_restart_interval) { +- ret = coda_jpeg_put_word(DRI_MARKER, &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_word(4, &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_word(ctx->params.jpeg_restart_interval, +- &stream); +- if (ret < 0) +- return ret; +- } +- +- /* Define Quantization Tables */ +- ret = coda_jpeg_define_quantization_table(ctx, 0x00, &stream); +- if (ret < 0) +- return ret; +- if (chroma_format != CODA9_JPEG_FORMAT_400) { +- ret = coda_jpeg_define_quantization_table(ctx, 0x01, &stream); +- if (ret < 0) +- return ret; +- } +- +- /* Define Huffman Tables */ +- ret = coda_jpeg_define_huffman_table(0x00, luma_dc, 16 + 12, &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_define_huffman_table(0x10, luma_ac, 16 + 162, &stream); +- if (ret < 0) +- return ret; +- if (chroma_format != CODA9_JPEG_FORMAT_400) { +- ret = coda_jpeg_define_huffman_table(0x01, chroma_dc, 16 + 12, +- &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_define_huffman_table(0x11, chroma_ac, 16 + 162, +- &stream); +- if (ret < 0) +- return ret; +- } +- +- /* Start Of Frame */ +- ret = coda_jpeg_put_word(SOF_MARKER, &stream); +- if (ret < 0) +- return ret; +- comp_num = (chroma_format == CODA9_JPEG_FORMAT_400) ? 1 : 3; +- ret = coda_jpeg_put_word(8 + comp_num * 3, &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_byte(0x08, &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_word(q_data_src->height, &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_word(q_data_src->width, &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_byte(comp_num, &stream); +- if (ret < 0) +- return ret; +- for (i = 0; i < comp_num; i++) { +- static unsigned char subsampling[5][3] = { +- [CODA9_JPEG_FORMAT_420] = { 0x22, 0x11, 0x11 }, +- [CODA9_JPEG_FORMAT_422] = { 0x21, 0x11, 0x11 }, +- [CODA9_JPEG_FORMAT_224] = { 0x12, 0x11, 0x11 }, +- [CODA9_JPEG_FORMAT_444] = { 0x11, 0x11, 0x11 }, +- [CODA9_JPEG_FORMAT_400] = { 0x11 }, +- }; +- +- /* Component identifier, matches SOS */ +- ret = coda_jpeg_put_byte(i + 1, &stream); +- if (ret < 0) +- return ret; +- ret = coda_jpeg_put_byte(subsampling[chroma_format][i], +- &stream); +- if (ret < 0) +- return ret; +- /* Chroma table index */ +- ret = coda_jpeg_put_byte((i == 0) ? 0 : 1, &stream); +- if (ret < 0) +- return ret; +- } +- +- /* Pad to multiple of 8 bytes */ +- pad = (stream.curr - buf) % 8; +- if (pad) { +- pad = 8 - pad; +- while (pad--) { +- ret = coda_jpeg_put_byte(0x00, &stream); +- if (ret < 0) +- return ret; +- } +- } +- +- return stream.curr - buf; +-} +- +-/* +- * Scale quantization table using nonlinear scaling factor +- * u8 qtab[64], scale [50,190] +- */ +-static void coda_scale_quant_table(u8 *q_tab, int scale) +-{ +- unsigned int temp; +- int i; +- +- for (i = 0; i < 64; i++) { +- temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100); +- if (temp <= 0) +- temp = 1; +- if (temp > 255) +- temp = 255; +- q_tab[i] = (unsigned char)temp; +- } +-} +- +-void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality) +-{ +- unsigned int scale; +- +- ctx->params.jpeg_quality = quality; +- +- /* Clip quality setting to [5,100] interval */ +- if (quality > 100) +- quality = 100; +- if (quality < 5) +- quality = 5; +- +- /* +- * Non-linear scaling factor: +- * [5,50] -> [1000..100], [51,100] -> [98..0] +- */ +- if (quality < 50) +- scale = 5000 / quality; +- else +- scale = 200 - 2 * quality; +- +- if (ctx->params.jpeg_qmat_tab[0]) { +- memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64); +- coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale); +- } +- if (ctx->params.jpeg_qmat_tab[1]) { +- memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64); +- coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale); +- } +-} +- +-/* +- * Encoder context operations +- */ +- +-static int coda9_jpeg_start_encoding(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- int ret; +- +- ret = coda9_jpeg_load_huff_tab(ctx); +- if (ret < 0) { +- v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n"); +- return ret; +- } +- if (!ctx->params.jpeg_qmat_tab[0]) { +- ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[0]) +- return -ENOMEM; +- } +- if (!ctx->params.jpeg_qmat_tab[1]) { +- ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[1]) +- return -ENOMEM; +- } +- coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); +- +- return 0; +-} +- +-static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx) +-{ +- struct coda_q_data *q_data_src; +- struct vb2_v4l2_buffer *src_buf, *dst_buf; +- struct coda_dev *dev = ctx->dev; +- u32 start_addr, end_addr; +- u16 aligned_width, aligned_height; +- bool chroma_interleave; +- int chroma_format; +- int header_len; +- int ret; +- ktime_t timeout; +- +- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); +- dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- +- if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0) +- vb2_set_plane_payload(&src_buf->vb2_buf, 0, +- vb2_plane_size(&src_buf->vb2_buf, 0)); +- +- src_buf->sequence = ctx->osequence; +- dst_buf->sequence = ctx->osequence; +- ctx->osequence++; +- +- src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; +- src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME; +- +- coda_set_gdi_regs(ctx); +- +- start_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); +- end_addr = start_addr + vb2_plane_size(&dst_buf->vb2_buf, 0); +- +- chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc); +- if (chroma_format < 0) +- return chroma_format; +- +- /* Round image dimensions to multiple of MCU size */ +- aligned_width = round_up(q_data_src->width, width_align[chroma_format]); +- aligned_height = round_up(q_data_src->height, +- height_align[chroma_format]); +- if (aligned_width != q_data_src->bytesperline) { +- v4l2_err(&dev->v4l2_dev, "wrong stride: %d instead of %d\n", +- aligned_width, q_data_src->bytesperline); +- } +- +- header_len = +- coda9_jpeg_encode_header(ctx, +- vb2_plane_size(&dst_buf->vb2_buf, 0), +- vb2_plane_vaddr(&dst_buf->vb2_buf, 0)); +- if (header_len < 0) +- return header_len; +- +- coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_BAS_ADDR); +- coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_END_ADDR); +- coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_WR_PTR); +- coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_RD_PTR); +- coda_write(dev, 0, CODA9_REG_JPEG_BBC_CUR_POS); +- /* 64 words per 256-byte page */ +- coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT); +- coda_write(dev, start_addr, CODA9_REG_JPEG_BBC_EXT_ADDR); +- coda_write(dev, 0, CODA9_REG_JPEG_BBC_INT_ADDR); +- +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR); +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR); +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); +- coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256), +- CODA9_REG_JPEG_BBC_STRM_CTRL); +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL); +- coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR); +- coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); +- coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR); +- coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR); +- +- chroma_interleave = (q_data_src->fourcc == V4L2_PIX_FMT_NV12); +- coda_write(dev, CODA9_JPEG_PIC_CTRL_TC_DIRECTION | +- CODA9_JPEG_PIC_CTRL_ENCODER_EN, CODA9_REG_JPEG_PIC_CTRL); +- coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO); +- coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG); +- coda_write(dev, ctx->params.jpeg_restart_interval, +- CODA9_REG_JPEG_RST_INTVAL); +- coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL); +- +- coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO); +- +- coda9_jpeg_write_huff_tab(ctx); +- coda9_jpeg_load_qmat_tab(ctx); +- +- if (ctx->params.rot_mode & CODA_ROT_90) { +- aligned_width = aligned_height; +- aligned_height = q_data_src->bytesperline; +- if (chroma_format == CODA9_JPEG_FORMAT_422) +- chroma_format = CODA9_JPEG_FORMAT_224; +- else if (chroma_format == CODA9_JPEG_FORMAT_224) +- chroma_format = CODA9_JPEG_FORMAT_422; +- } +- /* These need to be multiples of MCU size */ +- coda_write(dev, aligned_width << 16 | aligned_height, +- CODA9_REG_JPEG_PIC_SIZE); +- coda_write(dev, ctx->params.rot_mode ? +- (CODA_ROT_MIR_ENABLE | ctx->params.rot_mode) : 0, +- CODA9_REG_JPEG_ROT_INFO); +- +- coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO); +- +- coda_write(dev, 1, CODA9_GDI_CONTROL); +- timeout = ktime_add_us(ktime_get(), 100000); +- do { +- ret = coda_read(dev, CODA9_GDI_STATUS); +- if (ktime_compare(ktime_get(), timeout) > 0) { +- v4l2_err(&dev->v4l2_dev, "timeout waiting for GDI\n"); +- return -ETIMEDOUT; +- } +- } while (!ret); +- +- coda_write(dev, (chroma_format << 17) | (chroma_interleave << 16) | +- q_data_src->bytesperline, CODA9_GDI_INFO_CONTROL); +- /* The content of this register seems to be irrelevant: */ +- coda_write(dev, aligned_width << 16 | aligned_height, +- CODA9_GDI_INFO_PIC_SIZE); +- +- coda_write_base(ctx, q_data_src, src_buf, CODA9_GDI_INFO_BASE_Y); +- +- coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00); +- coda_write(dev, 0, CODA9_GDI_CONTROL); +- coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST); +- +- coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR); +- coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN); +- +- trace_coda_jpeg_run(ctx, src_buf); +- +- coda_write(dev, 1, CODA9_REG_JPEG_PIC_START); +- +- return 0; +-} +- +-static void coda9_jpeg_finish_encode(struct coda_ctx *ctx) +-{ +- struct vb2_v4l2_buffer *src_buf, *dst_buf; +- struct coda_dev *dev = ctx->dev; +- u32 wr_ptr, start_ptr; +- u32 err_mb; +- +- if (ctx->aborting) { +- coda_write(ctx->dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); +- return; +- } +- +- /* +- * Lock to make sure that an encoder stop command running in parallel +- * will either already have marked src_buf as last, or it will wake up +- * the capture queue after the buffers are returned. +- */ +- mutex_lock(&ctx->wakeup_mutex); +- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); +- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); +- +- trace_coda_jpeg_done(ctx, dst_buf); +- +- /* +- * Set plane payload to the number of bytes written out +- * by the JPEG processing unit +- */ +- start_ptr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); +- wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); +- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr); +- +- err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); +- if (err_mb) +- coda_dbg(1, ctx, "ERRMB: 0x%x\n", err_mb); +- +- coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); +- +- dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST); +- dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; +- dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST; +- +- v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); +- +- v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); +- coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR : +- VB2_BUF_STATE_DONE); +- mutex_unlock(&ctx->wakeup_mutex); +- +- coda_dbg(1, ctx, "job finished: encoded frame (%u)%s\n", +- dst_buf->sequence, +- (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : ""); +- +- /* +- * Reset JPEG processing unit after each encode run to work +- * around hangups when switching context between encoder and +- * decoder. +- */ +- coda_hw_reset(ctx); +-} +- +-static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- u32 end_addr, wr_ptr; +- +- /* Handle missing BBC overflow interrupt via timeout */ +- end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR); +- wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); +- if (wr_ptr >= end_addr - 256) { +- v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n"); +- coda9_jpeg_finish_encode(ctx); +- return; +- } +- +- coda_hw_reset(ctx); +-} +- +-static void coda9_jpeg_release(struct coda_ctx *ctx) +-{ +- int i; +- +- if (ctx->params.jpeg_qmat_tab[0] == luma_q) +- ctx->params.jpeg_qmat_tab[0] = NULL; +- if (ctx->params.jpeg_qmat_tab[1] == chroma_q) +- ctx->params.jpeg_qmat_tab[1] = NULL; +- for (i = 0; i < 3; i++) +- kfree(ctx->params.jpeg_qmat_tab[i]); +- kfree(ctx->params.jpeg_huff_data); +- kfree(ctx->params.jpeg_huff_tab); +-} +- +-const struct coda_context_ops coda9_jpeg_encode_ops = { +- .queue_init = coda_encoder_queue_init, +- .start_streaming = coda9_jpeg_start_encoding, +- .prepare_run = coda9_jpeg_prepare_encode, +- .finish_run = coda9_jpeg_finish_encode, +- .run_timeout = coda9_jpeg_encode_timeout, +- .release = coda9_jpeg_release, +-}; +- +-/* +- * Decoder context operations +- */ +- +-static int coda9_jpeg_start_decoding(struct coda_ctx *ctx) +-{ +- ctx->params.jpeg_qmat_index[0] = 0; +- ctx->params.jpeg_qmat_index[1] = 1; +- ctx->params.jpeg_qmat_index[2] = 1; +- ctx->params.jpeg_qmat_tab[0] = luma_q; +- ctx->params.jpeg_qmat_tab[1] = chroma_q; +- /* nothing more to do here */ +- +- /* TODO: we could already scan the first header to get the chroma +- * format. +- */ +- +- return 0; +-} +- +-static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- int aligned_width, aligned_height; +- int chroma_format; +- int ret; +- u32 val, dst_fourcc; +- struct coda_q_data *q_data_src, *q_data_dst; +- struct vb2_v4l2_buffer *src_buf, *dst_buf; +- int chroma_interleave; +- int scl_hor_mode, scl_ver_mode; +- +- src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); +- dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- dst_fourcc = q_data_dst->fourcc; +- +- scl_hor_mode = coda_jpeg_scale(q_data_src->width, q_data_dst->width); +- scl_ver_mode = coda_jpeg_scale(q_data_src->height, q_data_dst->height); +- +- if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0) +- vb2_set_plane_payload(&src_buf->vb2_buf, 0, +- vb2_plane_size(&src_buf->vb2_buf, 0)); +- +- chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc); +- if (chroma_format < 0) +- return chroma_format; +- +- ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf); +- if (ret < 0) { +- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); +- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); +- v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); +- v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); +- +- return ret; +- } +- +- /* Round image dimensions to multiple of MCU size */ +- aligned_width = round_up(q_data_src->width, width_align[chroma_format]); +- aligned_height = round_up(q_data_src->height, height_align[chroma_format]); +- if (aligned_width != q_data_dst->bytesperline) { +- v4l2_err(&dev->v4l2_dev, "stride mismatch: %d != %d\n", +- aligned_width, q_data_dst->bytesperline); +- } +- +- coda_set_gdi_regs(ctx); +- +- val = ctx->params.jpeg_huff_ac_index[0] << 12 | +- ctx->params.jpeg_huff_ac_index[1] << 11 | +- ctx->params.jpeg_huff_ac_index[2] << 10 | +- ctx->params.jpeg_huff_dc_index[0] << 9 | +- ctx->params.jpeg_huff_dc_index[1] << 8 | +- ctx->params.jpeg_huff_dc_index[2] << 7; +- if (ctx->params.jpeg_huff_tab) +- val |= CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN; +- coda_write(dev, val, CODA9_REG_JPEG_PIC_CTRL); +- +- coda_write(dev, aligned_width << 16 | aligned_height, +- CODA9_REG_JPEG_PIC_SIZE); +- +- chroma_interleave = (dst_fourcc == V4L2_PIX_FMT_NV12); +- coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO); +- coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO); +- coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO); +- if (scl_hor_mode || scl_ver_mode) +- val = CODA9_JPEG_SCL_ENABLE | (scl_hor_mode << 2) | scl_ver_mode; +- else +- val = 0; +- coda_write(dev, val, CODA9_REG_JPEG_SCL_INFO); +- coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG); +- coda_write(dev, ctx->params.jpeg_restart_interval, +- CODA9_REG_JPEG_RST_INTVAL); +- +- if (ctx->params.jpeg_huff_tab) +- coda9_jpeg_dec_huff_setup(ctx); +- +- coda9_jpeg_qmat_setup(ctx); +- +- coda9_jpeg_dec_bbc_gbu_setup(ctx, &src_buf->vb2_buf, +- ctx->jpeg_ecs_offset); +- +- coda_write(dev, 0, CODA9_REG_JPEG_RST_INDEX); +- coda_write(dev, 0, CODA9_REG_JPEG_RST_COUNT); +- +- coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_Y); +- coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CB); +- coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CR); +- +- coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO); +- +- coda_write(dev, 1, CODA9_GDI_CONTROL); +- do { +- ret = coda_read(dev, CODA9_GDI_STATUS); +- } while (!ret); +- +- val = (chroma_format << 17) | (chroma_interleave << 16) | +- q_data_dst->bytesperline; +- if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) +- val |= 3 << 20; +- coda_write(dev, val, CODA9_GDI_INFO_CONTROL); +- +- coda_write(dev, aligned_width << 16 | aligned_height, +- CODA9_GDI_INFO_PIC_SIZE); +- +- coda_write_base(ctx, q_data_dst, dst_buf, CODA9_GDI_INFO_BASE_Y); +- +- coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00); +- coda_write(dev, 0, CODA9_GDI_CONTROL); +- coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST); +- +- trace_coda_jpeg_run(ctx, src_buf); +- +- coda_write(dev, 1, CODA9_REG_JPEG_PIC_START); +- +- return 0; +-} +- +-static void coda9_jpeg_finish_decode(struct coda_ctx *ctx) +-{ +- struct coda_dev *dev = ctx->dev; +- struct vb2_v4l2_buffer *dst_buf, *src_buf; +- struct coda_q_data *q_data_dst; +- u32 err_mb; +- +- err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); +- if (err_mb) +- v4l2_err(&dev->v4l2_dev, "ERRMB: 0x%x\n", err_mb); +- +- coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD); +- +- /* +- * Lock to make sure that a decoder stop command running in parallel +- * will either already have marked src_buf as last, or it will wake up +- * the capture queue after the buffers are returned. +- */ +- mutex_lock(&ctx->wakeup_mutex); +- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); +- dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); +- dst_buf->sequence = ctx->osequence++; +- +- trace_coda_jpeg_done(ctx, dst_buf); +- +- dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST); +- dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; +- dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST; +- +- v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false); +- +- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); +- vb2_set_plane_payload(&dst_buf->vb2_buf, 0, q_data_dst->sizeimage); +- +- v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); +- coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR : +- VB2_BUF_STATE_DONE); +- +- mutex_unlock(&ctx->wakeup_mutex); +- +- coda_dbg(1, ctx, "job finished: decoded frame (%u)%s\n", +- dst_buf->sequence, +- (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : ""); +- +- /* +- * Reset JPEG processing unit after each decode run to work +- * around hangups when switching context between encoder and +- * decoder. +- */ +- coda_hw_reset(ctx); +-} +- +-const struct coda_context_ops coda9_jpeg_decode_ops = { +- .queue_init = coda_encoder_queue_init, /* non-bitstream operation */ +- .start_streaming = coda9_jpeg_start_decoding, +- .prepare_run = coda9_jpeg_prepare_decode, +- .finish_run = coda9_jpeg_finish_decode, +- .release = coda9_jpeg_release, +-}; +- +-irqreturn_t coda9_jpeg_irq_handler(int irq, void *data) +-{ +- struct coda_dev *dev = data; +- struct coda_ctx *ctx; +- int status; +- int err_mb; +- +- status = coda_read(dev, CODA9_REG_JPEG_PIC_STATUS); +- if (status == 0) +- return IRQ_HANDLED; +- coda_write(dev, status, CODA9_REG_JPEG_PIC_STATUS); +- +- if (status & CODA9_JPEG_STATUS_OVERFLOW) +- v4l2_err(&dev->v4l2_dev, "JPEG overflow\n"); +- +- if (status & CODA9_JPEG_STATUS_BBC_INT) +- v4l2_err(&dev->v4l2_dev, "JPEG BBC interrupt\n"); +- +- if (status & CODA9_JPEG_STATUS_ERROR) { +- v4l2_err(&dev->v4l2_dev, "JPEG error\n"); +- +- err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB); +- if (err_mb) { +- v4l2_err(&dev->v4l2_dev, +- "ERRMB: 0x%x: rst idx %d, mcu pos (%d,%d)\n", +- err_mb, err_mb >> 24, (err_mb >> 12) & 0xfff, +- err_mb & 0xfff); +- } +- } +- +- ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); +- if (!ctx) { +- v4l2_err(&dev->v4l2_dev, +- "Instance released before the end of transaction\n"); +- mutex_unlock(&dev->coda_mutex); +- return IRQ_HANDLED; +- } +- +- complete(&ctx->completion); +- +- return IRQ_HANDLED; +-} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-mpeg2.c b/drivers/media/platform/chips-media/coda-mpeg2.c +--- a/drivers/media/platform/chips-media/coda-mpeg2.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda-mpeg2.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,87 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Coda multi-standard codec IP - MPEG-2 helper functions +- * +- * Copyright (C) 2019 Pengutronix, Philipp Zabel +- */ +- +-#include +-#include +-#include "coda.h" +- +-int coda_mpeg2_profile(int profile_idc) +-{ +- switch (profile_idc) { +- case 5: +- return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE; +- case 4: +- return V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN; +- case 3: +- return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE; +- case 2: +- return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE; +- case 1: +- return V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH; +- default: +- return -EINVAL; +- } +-} +- +-int coda_mpeg2_level(int level_idc) +-{ +- switch (level_idc) { +- case 10: +- return V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW; +- case 8: +- return V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN; +- case 6: +- return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440; +- case 4: +- return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH; +- default: +- return -EINVAL; +- } +-} +- +-/* +- * Check if the buffer starts with the MPEG-2 sequence header (with or without +- * quantization matrix) and extension header, for example: +- * +- * 00 00 01 b3 2d 01 e0 34 08 8b a3 81 +- * 10 11 11 12 12 12 13 13 13 13 14 14 14 14 14 15 +- * 15 15 15 15 15 16 16 16 16 16 16 16 17 17 17 17 +- * 17 17 17 17 18 18 18 19 18 18 18 19 1a 1a 1a 1a +- * 19 1b 1b 1b 1b 1b 1c 1c 1c 1c 1e 1e 1e 1f 1f 21 +- * 00 00 01 b5 14 8a 00 01 00 00 +- * +- * or: +- * +- * 00 00 01 b3 08 00 40 15 ff ff e0 28 +- * 00 00 01 b5 14 8a 00 01 00 00 +- * +- * Returns the detected header size in bytes or 0. +- */ +-u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size) +-{ +- static const u8 sequence_header_start[4] = { 0x00, 0x00, 0x01, 0xb3 }; +- static const union { +- u8 extension_start[4]; +- u8 start_code_prefix[3]; +- } u = { { 0x00, 0x00, 0x01, 0xb5 } }; +- +- if (size < 22 || +- memcmp(buf, sequence_header_start, 4) != 0) +- return 0; +- +- if ((size == 22 || +- (size >= 25 && memcmp(buf + 22, u.start_code_prefix, 3) == 0)) && +- memcmp(buf + 12, u.extension_start, 4) == 0) +- return 22; +- +- if ((size == 86 || +- (size > 89 && memcmp(buf + 86, u.start_code_prefix, 3) == 0)) && +- memcmp(buf + 76, u.extension_start, 4) == 0) +- return 86; +- +- return 0; +-} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-mpeg4.c b/drivers/media/platform/chips-media/coda-mpeg4.c +--- a/drivers/media/platform/chips-media/coda-mpeg4.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda-mpeg4.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,87 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +-/* +- * Coda multi-standard codec IP - MPEG-4 helper functions +- * +- * Copyright (C) 2019 Pengutronix, Philipp Zabel +- */ +- +-#include +-#include +- +-#include "coda.h" +- +-int coda_mpeg4_profile(int profile_idc) +-{ +- switch (profile_idc) { +- case 0: +- return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE; +- case 15: +- return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE; +- case 2: +- return V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE; +- case 1: +- return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE; +- case 11: +- return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY; +- default: +- return -EINVAL; +- } +-} +- +-int coda_mpeg4_level(int level_idc) +-{ +- switch (level_idc) { +- case 0: +- return V4L2_MPEG_VIDEO_MPEG4_LEVEL_0; +- case 1: +- return V4L2_MPEG_VIDEO_MPEG4_LEVEL_1; +- case 2: +- return V4L2_MPEG_VIDEO_MPEG4_LEVEL_2; +- case 3: +- return V4L2_MPEG_VIDEO_MPEG4_LEVEL_3; +- case 4: +- return V4L2_MPEG_VIDEO_MPEG4_LEVEL_4; +- case 5: +- return V4L2_MPEG_VIDEO_MPEG4_LEVEL_5; +- default: +- return -EINVAL; +- } +-} +- +-/* +- * Check if the buffer starts with the MPEG-4 visual object sequence and visual +- * object headers, for example: +- * +- * 00 00 01 b0 f1 +- * 00 00 01 b5 a9 13 00 00 01 00 00 00 01 20 08 +- * d4 8d 88 00 f5 04 04 08 14 30 3f +- * +- * Returns the detected header size in bytes or 0. +- */ +-u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size) +-{ +- static const u8 vos_start[4] = { 0x00, 0x00, 0x01, 0xb0 }; +- static const union { +- u8 vo_start[4]; +- u8 start_code_prefix[3]; +- } u = { { 0x00, 0x00, 0x01, 0xb5 } }; +- +- if (size < 30 || +- memcmp(buf, vos_start, 4) != 0 || +- memcmp(buf + 5, u.vo_start, 4) != 0) +- return 0; +- +- if (size == 30 || +- (size >= 33 && memcmp(buf + 30, u.start_code_prefix, 3) == 0)) +- return 30; +- +- if (size == 31 || +- (size >= 34 && memcmp(buf + 31, u.start_code_prefix, 3) == 0)) +- return 31; +- +- if (size == 32 || +- (size >= 35 && memcmp(buf + 32, u.start_code_prefix, 3) == 0)) +- return 32; +- +- return 0; +-} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda_regs.h b/drivers/media/platform/chips-media/coda_regs.h +--- a/drivers/media/platform/chips-media/coda_regs.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/coda_regs.h 1969-12-31 19:00:00.000000000 -0500 +@@ -1,563 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-or-later */ +-/* +- * linux/drivers/media/platform/chips-media/coda_regs.h +- * +- * Copyright (C) 2012 Vista Silicon SL +- * Javier Martin +- * Xavier Duret +- */ +- +-#ifndef _REGS_CODA_H_ +-#define _REGS_CODA_H_ +- +-/* HW registers */ +-#define CODA_REG_BIT_CODE_RUN 0x000 +-#define CODA_REG_RUN_ENABLE (1 << 0) +-#define CODA_REG_BIT_CODE_DOWN 0x004 +-#define CODA_DOWN_ADDRESS_SET(x) (((x) & 0xffff) << 16) +-#define CODA_DOWN_DATA_SET(x) ((x) & 0xffff) +-#define CODA_REG_BIT_HOST_IN_REQ 0x008 +-#define CODA_REG_BIT_INT_CLEAR 0x00c +-#define CODA_REG_BIT_INT_CLEAR_SET 0x1 +-#define CODA_REG_BIT_INT_STATUS 0x010 +-#define CODA_REG_BIT_CODE_RESET 0x014 +-#define CODA_REG_RESET_ENABLE (1 << 0) +-#define CODA_REG_BIT_CUR_PC 0x018 +-#define CODA9_REG_BIT_SW_RESET 0x024 +-#define CODA9_SW_RESET_BPU_CORE 0x008 +-#define CODA9_SW_RESET_BPU_BUS 0x010 +-#define CODA9_SW_RESET_VCE_CORE 0x020 +-#define CODA9_SW_RESET_VCE_BUS 0x040 +-#define CODA9_SW_RESET_GDI_CORE 0x080 +-#define CODA9_SW_RESET_GDI_BUS 0x100 +-#define CODA9_REG_BIT_SW_RESET_STATUS 0x034 +- +-/* Static SW registers */ +-#define CODA_REG_BIT_CODE_BUF_ADDR 0x100 +-#define CODA_REG_BIT_WORK_BUF_ADDR 0x104 +-#define CODA_REG_BIT_PARA_BUF_ADDR 0x108 +-#define CODA_REG_BIT_STREAM_CTRL 0x10c +-#define CODA7_STREAM_BUF_PIC_RESET (1 << 4) +-#define CODADX6_STREAM_BUF_PIC_RESET (1 << 3) +-#define CODA7_STREAM_BUF_PIC_FLUSH (1 << 3) +-#define CODADX6_STREAM_BUF_PIC_FLUSH (1 << 2) +-#define CODA7_STREAM_BUF_DYNALLOC_EN (1 << 5) +-#define CODADX6_STREAM_BUF_DYNALLOC_EN (1 << 4) +-#define CODADX6_STREAM_CHKDIS_OFFSET (1 << 1) +-#define CODA7_STREAM_SEL_64BITS_ENDIAN (1 << 1) +-#define CODA_STREAM_ENDIAN_SELECT (1 << 0) +-#define CODA_REG_BIT_FRAME_MEM_CTRL 0x110 +-#define CODA9_FRAME_ENABLE_BWB (1 << 12) +-#define CODA9_FRAME_TILED2LINEAR (1 << 11) +-#define CODA_FRAME_CHROMA_INTERLEAVE (1 << 2) +-#define CODA_IMAGE_ENDIAN_SELECT (1 << 0) +-#define CODA_REG_BIT_BIT_STREAM_PARAM 0x114 +-#define CODA_BIT_STREAM_END_FLAG (1 << 2) +-#define CODA_BIT_DEC_SEQ_INIT_ESCAPE (1 << 0) +-#define CODA_REG_BIT_TEMP_BUF_ADDR 0x118 +-#define CODA_REG_BIT_RD_PTR(x) (0x120 + 8 * (x)) +-#define CODA_REG_BIT_WR_PTR(x) (0x124 + 8 * (x)) +-#define CODA_REG_BIT_FRM_DIS_FLG(x) (0x150 + 4 * (x)) +-#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR 0x140 +-#define CODA7_REG_BIT_AXI_SRAM_USE 0x140 +-#define CODA9_USE_HOST_BTP_ENABLE (1 << 13) +-#define CODA9_USE_HOST_OVL_ENABLE (1 << 12) +-#define CODA7_USE_HOST_ME_ENABLE (1 << 11) +-#define CODA9_USE_HOST_DBK_ENABLE (3 << 10) +-#define CODA7_USE_HOST_OVL_ENABLE (1 << 10) +-#define CODA7_USE_HOST_DBK_ENABLE (1 << 9) +-#define CODA9_USE_HOST_IP_ENABLE (1 << 9) +-#define CODA7_USE_HOST_IP_ENABLE (1 << 8) +-#define CODA9_USE_HOST_BIT_ENABLE (1 << 8) +-#define CODA7_USE_HOST_BIT_ENABLE (1 << 7) +-#define CODA9_USE_BTP_ENABLE (1 << 5) +-#define CODA7_USE_ME_ENABLE (1 << 4) +-#define CODA9_USE_OVL_ENABLE (1 << 4) +-#define CODA7_USE_OVL_ENABLE (1 << 3) +-#define CODA9_USE_DBK_ENABLE (3 << 2) +-#define CODA7_USE_DBK_ENABLE (1 << 2) +-#define CODA7_USE_IP_ENABLE (1 << 1) +-#define CODA7_USE_BIT_ENABLE (1 << 0) +- +-#define CODA_REG_BIT_BUSY 0x160 +-#define CODA_REG_BIT_BUSY_FLAG 1 +-#define CODA_REG_BIT_RUN_COMMAND 0x164 +-#define CODA_COMMAND_SEQ_INIT 1 +-#define CODA_COMMAND_SEQ_END 2 +-#define CODA_COMMAND_PIC_RUN 3 +-#define CODA_COMMAND_SET_FRAME_BUF 4 +-#define CODA_COMMAND_ENCODE_HEADER 5 +-#define CODA_COMMAND_ENC_PARA_SET 6 +-#define CODA_COMMAND_DEC_PARA_SET 7 +-#define CODA_COMMAND_DEC_BUF_FLUSH 8 +-#define CODA_COMMAND_RC_CHANGE_PARAMETER 9 +-#define CODA_COMMAND_FIRMWARE_GET 0xf +-#define CODA_REG_BIT_RUN_INDEX 0x168 +-#define CODA_INDEX_SET(x) ((x) & 0x3) +-#define CODA_REG_BIT_RUN_COD_STD 0x16c +-#define CODADX6_MODE_DECODE_MP4 0 +-#define CODADX6_MODE_ENCODE_MP4 1 +-#define CODADX6_MODE_DECODE_H264 2 +-#define CODADX6_MODE_ENCODE_H264 3 +-#define CODA7_MODE_DECODE_H264 0 +-#define CODA7_MODE_DECODE_VC1 1 +-#define CODA7_MODE_DECODE_MP2 2 +-#define CODA7_MODE_DECODE_MP4 3 +-#define CODA7_MODE_DECODE_DV3 3 +-#define CODA7_MODE_DECODE_RV 4 +-#define CODA7_MODE_DECODE_MJPG 5 +-#define CODA7_MODE_ENCODE_H264 8 +-#define CODA7_MODE_ENCODE_MP4 11 +-#define CODA7_MODE_ENCODE_MJPG 13 +-#define CODA9_MODE_DECODE_H264 0 +-#define CODA9_MODE_DECODE_VC1 1 +-#define CODA9_MODE_DECODE_MP2 2 +-#define CODA9_MODE_DECODE_MP4 3 +-#define CODA9_MODE_DECODE_DV3 3 +-#define CODA9_MODE_DECODE_RV 4 +-#define CODA9_MODE_DECODE_AVS 5 +-#define CODA9_MODE_DECODE_MJPG 6 +-#define CODA9_MODE_DECODE_VPX 7 +-#define CODA9_MODE_ENCODE_H264 8 +-#define CODA9_MODE_ENCODE_MP4 11 +-#define CODA9_MODE_ENCODE_MJPG 13 +-#define CODA_MODE_INVALID 0xffff +-#define CODA_REG_BIT_INT_ENABLE 0x170 +-#define CODA_INT_INTERRUPT_ENABLE (1 << 3) +-#define CODA_REG_BIT_INT_REASON 0x174 +-#define CODA7_REG_BIT_RUN_AUX_STD 0x178 +-#define CODA_MP4_AUX_MPEG4 0 +-#define CODA_MP4_AUX_DIVX3 1 +-#define CODA_VPX_AUX_THO 0 +-#define CODA_VPX_AUX_VP6 1 +-#define CODA_VPX_AUX_VP8 2 +-#define CODA_H264_AUX_AVC 0 +-#define CODA_H264_AUX_MVC 1 +- +-/* +- * Commands' mailbox: +- * registers with offsets in the range 0x180-0x1d0 +- * have different meaning depending on the command being +- * issued. +- */ +- +-/* Decoder Sequence Initialization */ +-#define CODA_CMD_DEC_SEQ_BB_START 0x180 +-#define CODA_CMD_DEC_SEQ_BB_SIZE 0x184 +-#define CODA_CMD_DEC_SEQ_OPTION 0x188 +-#define CODA_NO_INT_ENABLE (1 << 10) +-#define CODA_REORDER_ENABLE (1 << 1) +-#define CODADX6_QP_REPORT (1 << 0) +-#define CODA7_MP4_DEBLK_ENABLE (1 << 0) +-#define CODA_CMD_DEC_SEQ_SRC_SIZE 0x18c +-#define CODA_CMD_DEC_SEQ_START_BYTE 0x190 +-#define CODA_CMD_DEC_SEQ_PS_BB_START 0x194 +-#define CODA_CMD_DEC_SEQ_PS_BB_SIZE 0x198 +-#define CODA_CMD_DEC_SEQ_JPG_THUMB_EN 0x19c +-#define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS 0x19c +-#define CODA_MP4_CLASS_MPEG4 0 +-#define CODA_CMD_DEC_SEQ_X264_MV_EN 0x19c +-#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE 0x1a0 +- +-#define CODA7_RET_DEC_SEQ_ASPECT 0x1b0 +-#define CODA9_RET_DEC_SEQ_BITRATE 0x1b4 +-#define CODA_RET_DEC_SEQ_SUCCESS 0x1c0 +-#define CODA_RET_DEC_SEQ_SRC_FMT 0x1c4 /* SRC_SIZE on CODA7 */ +-#define CODA_RET_DEC_SEQ_SRC_SIZE 0x1c4 +-#define CODA_RET_DEC_SEQ_SRC_F_RATE 0x1c8 +-#define CODA9_RET_DEC_SEQ_ASPECT 0x1c8 +-#define CODA_RET_DEC_SEQ_FRAME_NEED 0x1cc +-#define CODA_RET_DEC_SEQ_FRAME_DELAY 0x1d0 +-#define CODA_RET_DEC_SEQ_INFO 0x1d4 +-#define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT 0x1d8 +-#define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM 0x1dc +-#define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM 0x1e0 +-#define CODA_RET_DEC_SEQ_ERR_REASON 0x1e0 +-#define CODA_RET_DEC_SEQ_FRATE_NR 0x1e4 +-#define CODA_RET_DEC_SEQ_FRATE_DR 0x1e8 +-#define CODA_RET_DEC_SEQ_JPG_PARA 0x1e4 +-#define CODA_RET_DEC_SEQ_JPG_THUMB_IND 0x1e8 +-#define CODA7_RET_DEC_SEQ_HEADER_REPORT 0x1ec +- +-/* Decoder Picture Run */ +-#define CODA_CMD_DEC_PIC_ROT_MODE 0x180 +-#define CODA_CMD_DEC_PIC_ROT_ADDR_Y 0x184 +-#define CODA9_CMD_DEC_PIC_ROT_INDEX 0x184 +-#define CODA_CMD_DEC_PIC_ROT_ADDR_CB 0x188 +-#define CODA9_CMD_DEC_PIC_ROT_ADDR_Y 0x188 +-#define CODA_CMD_DEC_PIC_ROT_ADDR_CR 0x18c +-#define CODA9_CMD_DEC_PIC_ROT_ADDR_CB 0x18c +-#define CODA_CMD_DEC_PIC_ROT_STRIDE 0x190 +-#define CODA9_CMD_DEC_PIC_ROT_ADDR_CR 0x190 +-#define CODA9_CMD_DEC_PIC_ROT_STRIDE 0x1b8 +- +-#define CODA_CMD_DEC_PIC_OPTION 0x194 +-#define CODA_PRE_SCAN_EN (1 << 0) +-#define CODA_PRE_SCAN_MODE_DECODE (0 << 1) +-#define CODA_PRE_SCAN_MODE_RETURN (1 << 1) +-#define CODA_IFRAME_SEARCH_EN (1 << 2) +-#define CODA_SKIP_FRAME_MODE (0x3 << 3) +-#define CODA_CMD_DEC_PIC_SKIP_NUM 0x198 +-#define CODA_CMD_DEC_PIC_CHUNK_SIZE 0x19c +-#define CODA_CMD_DEC_PIC_BB_START 0x1a0 +-#define CODA_CMD_DEC_PIC_START_BYTE 0x1a4 +-#define CODA_RET_DEC_PIC_SIZE 0x1bc +-#define CODA_RET_DEC_PIC_FRAME_NUM 0x1c0 +-#define CODA_RET_DEC_PIC_FRAME_IDX 0x1c4 +-#define CODA_RET_DEC_PIC_ERR_MB 0x1c8 +-#define CODA_RET_DEC_PIC_TYPE 0x1cc +-#define CODA_PIC_TYPE_MASK 0x7 +-#define CODA_PIC_TYPE_MASK_VC1 0x3f +-#define CODA9_PIC_TYPE_FIRST_MASK (0x7 << 3) +-#define CODA9_PIC_TYPE_IDR_MASK (0x3 << 6) +-#define CODA7_PIC_TYPE_H264_NPF_MASK (0x3 << 16) +-#define CODA7_PIC_TYPE_INTERLACED (1 << 18) +-#define CODA_RET_DEC_PIC_POST 0x1d0 +-#define CODA_RET_DEC_PIC_MVC_REPORT 0x1d0 +-#define CODA_RET_DEC_PIC_OPTION 0x1d4 +-#define CODA_RET_DEC_PIC_SUCCESS 0x1d8 +-#define CODA_RET_DEC_PIC_CUR_IDX 0x1dc +-#define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT 0x1e0 +-#define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM 0x1e4 +-#define CODA_RET_DEC_PIC_FRAME_NEED 0x1ec +- +-#define CODA9_RET_DEC_PIC_VP8_PIC_REPORT 0x1e8 +-#define CODA9_RET_DEC_PIC_ASPECT 0x1f0 +-#define CODA9_RET_DEC_PIC_VP8_SCALE_INFO 0x1f0 +-#define CODA9_RET_DEC_PIC_FRATE_NR 0x1f4 +-#define CODA9_RET_DEC_PIC_FRATE_DR 0x1f8 +- +-/* Encoder Sequence Initialization */ +-#define CODA_CMD_ENC_SEQ_BB_START 0x180 +-#define CODA_CMD_ENC_SEQ_BB_SIZE 0x184 +-#define CODA_CMD_ENC_SEQ_OPTION 0x188 +-#define CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET 9 +-#define CODA9_OPTION_MVC_PREFIX_NAL_OFFSET 9 +-#define CODA7_OPTION_GAMMA_OFFSET 8 +-#define CODA9_OPTION_MVC_PARASET_REFRESH_OFFSET 8 +-#define CODA7_OPTION_RCQPMAX_OFFSET 7 +-#define CODA9_OPTION_GAMMA_OFFSET 7 +-#define CODADX6_OPTION_GAMMA_OFFSET 7 +-#define CODA7_OPTION_RCQPMIN_OFFSET 6 +-#define CODA9_OPTION_RCQPMAX_OFFSET 6 +-#define CODA_OPTION_LIMITQP_OFFSET 6 +-#define CODA_OPTION_RCINTRAQP_OFFSET 5 +-#define CODA_OPTION_FMO_OFFSET 4 +-#define CODA9_OPTION_MVC_INTERVIEW_OFFSET 4 +-#define CODA_OPTION_AVC_AUD_OFFSET 2 +-#define CODA_OPTION_SLICEREPORT_OFFSET 1 +-#define CODA_CMD_ENC_SEQ_COD_STD 0x18c +-#define CODA_STD_MPEG4 0 +-#define CODA9_STD_H264 0 +-#define CODA_STD_H263 1 +-#define CODA_STD_H264 2 +-#define CODA9_STD_MPEG4 3 +- +-#define CODA_CMD_ENC_SEQ_SRC_SIZE 0x190 +-#define CODA7_PICWIDTH_OFFSET 16 +-#define CODA7_PICWIDTH_MASK 0xffff +-#define CODADX6_PICWIDTH_OFFSET 10 +-#define CODADX6_PICWIDTH_MASK 0x3ff +-#define CODA_PICHEIGHT_OFFSET 0 +-#define CODADX6_PICHEIGHT_MASK 0x3ff +-#define CODA7_PICHEIGHT_MASK 0xffff +-#define CODA_CMD_ENC_SEQ_SRC_F_RATE 0x194 +-#define CODA_FRATE_RES_OFFSET 0 +-#define CODA_FRATE_RES_MASK 0xffff +-#define CODA_FRATE_DIV_OFFSET 16 +-#define CODA_FRATE_DIV_MASK 0xffff +-#define CODA_CMD_ENC_SEQ_MP4_PARA 0x198 +-#define CODA_MP4PARAM_VERID_OFFSET 6 +-#define CODA_MP4PARAM_VERID_MASK 0x01 +-#define CODA_MP4PARAM_INTRADCVLCTHR_OFFSET 2 +-#define CODA_MP4PARAM_INTRADCVLCTHR_MASK 0x07 +-#define CODA_MP4PARAM_REVERSIBLEVLCENABLE_OFFSET 1 +-#define CODA_MP4PARAM_REVERSIBLEVLCENABLE_MASK 0x01 +-#define CODA_MP4PARAM_DATAPARTITIONENABLE_OFFSET 0 +-#define CODA_MP4PARAM_DATAPARTITIONENABLE_MASK 0x01 +-#define CODA_CMD_ENC_SEQ_263_PARA 0x19c +-#define CODA_263PARAM_ANNEXJENABLE_OFFSET 2 +-#define CODA_263PARAM_ANNEXJENABLE_MASK 0x01 +-#define CODA_263PARAM_ANNEXKENABLE_OFFSET 1 +-#define CODA_263PARAM_ANNEXKENABLE_MASK 0x01 +-#define CODA_263PARAM_ANNEXTENABLE_OFFSET 0 +-#define CODA_263PARAM_ANNEXTENABLE_MASK 0x01 +-#define CODA_CMD_ENC_SEQ_264_PARA 0x1a0 +-#define CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET 12 +-#define CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK 0x0f +-#define CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET 8 +-#define CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK 0x0f +-#define CODA_264PARAM_DISABLEDEBLK_OFFSET 6 +-#define CODA_264PARAM_DISABLEDEBLK_MASK 0x03 +-#define CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET 5 +-#define CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_MASK 0x01 +-#define CODA_264PARAM_CHROMAQPOFFSET_OFFSET 0 +-#define CODA_264PARAM_CHROMAQPOFFSET_MASK 0x1f +-#define CODA_CMD_ENC_SEQ_SLICE_MODE 0x1a4 +-#define CODA_SLICING_SIZE_OFFSET 2 +-#define CODA_SLICING_SIZE_MASK 0x3fffffff +-#define CODA_SLICING_UNIT_OFFSET 1 +-#define CODA_SLICING_UNIT_MASK 0x01 +-#define CODA_SLICING_MODE_OFFSET 0 +-#define CODA_SLICING_MODE_MASK 0x01 +-#define CODA_CMD_ENC_SEQ_GOP_SIZE 0x1a8 +-#define CODA_GOP_SIZE_OFFSET 0 +-#define CODA_GOP_SIZE_MASK 0x3f +-#define CODA_CMD_ENC_SEQ_RC_PARA 0x1ac +-#define CODA_RATECONTROL_AUTOSKIP_OFFSET 31 +-#define CODA_RATECONTROL_AUTOSKIP_MASK 0x01 +-#define CODA_RATECONTROL_INITIALDELAY_OFFSET 16 +-#define CODA_RATECONTROL_INITIALDELAY_MASK 0x7fff +-#define CODA_RATECONTROL_BITRATE_OFFSET 1 +-#define CODA_RATECONTROL_BITRATE_MASK 0x7fff +-#define CODA_RATECONTROL_ENABLE_OFFSET 0 +-#define CODA_RATECONTROL_ENABLE_MASK 0x01 +-#define CODA_CMD_ENC_SEQ_RC_BUF_SIZE 0x1b0 +-#define CODA_CMD_ENC_SEQ_INTRA_REFRESH 0x1b4 +-#define CODADX6_CMD_ENC_SEQ_FMO 0x1b8 +-#define CODA_FMOPARAM_TYPE_OFFSET 4 +-#define CODA_FMOPARAM_TYPE_MASK 1 +-#define CODA_FMOPARAM_SLICENUM_OFFSET 0 +-#define CODA_FMOPARAM_SLICENUM_MASK 0x0f +-#define CODADX6_CMD_ENC_SEQ_INTRA_QP 0x1bc +-#define CODA7_CMD_ENC_SEQ_SEARCH_BASE 0x1b8 +-#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE 0x1bc +-#define CODA7_CMD_ENC_SEQ_INTRA_QP 0x1c4 +-#define CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX 0x1c8 +-#define CODA_QPMIN_OFFSET 8 +-#define CODA_QPMIN_MASK 0x3f +-#define CODA_QPMAX_OFFSET 0 +-#define CODA_QPMAX_MASK 0x3f +-#define CODA_CMD_ENC_SEQ_RC_GAMMA 0x1cc +-#define CODA_GAMMA_OFFSET 0 +-#define CODA_GAMMA_MASK 0xffff +-#define CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE 0x1d0 +-#define CODA9_CMD_ENC_SEQ_INTRA_WEIGHT 0x1d4 +-#define CODA9_CMD_ENC_SEQ_ME_OPTION 0x1d8 +-#define CODA_RET_ENC_SEQ_SUCCESS 0x1c0 +- +-#define CODA_CMD_ENC_SEQ_JPG_PARA 0x198 +-#define CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL 0x19C +-#define CODA_CMD_ENC_SEQ_JPG_THUMB_EN 0x1a0 +-#define CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE 0x1a4 +-#define CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET 0x1a8 +- +-/* Encoder Parameter Change */ +-#define CODA_CMD_ENC_PARAM_CHANGE_ENABLE 0x180 +-#define CODA_PARAM_CHANGE_RC_GOP BIT(0) +-#define CODA_PARAM_CHANGE_RC_INTRA_QP BIT(1) +-#define CODA_PARAM_CHANGE_RC_BITRATE BIT(2) +-#define CODA_PARAM_CHANGE_RC_FRAME_RATE BIT(3) +-#define CODA_PARAM_CHANGE_INTRA_MB_NUM BIT(4) +-#define CODA_PARAM_CHANGE_SLICE_MODE BIT(5) +-#define CODA_PARAM_CHANGE_HEC_MODE BIT(6) +-#define CODA_CMD_ENC_PARAM_RC_GOP 0x184 +-#define CODA_CMD_ENC_PARAM_RC_INTRA_QP 0x188 +-#define CODA_CMD_ENC_PARAM_RC_BITRATE 0x18c +-#define CODA_CMD_ENC_PARAM_RC_FRAME_RATE 0x190 +-#define CODA_CMD_ENC_PARAM_INTRA_MB_NUM 0x194 +-#define CODA_CMD_ENC_PARAM_SLICE_MODE 0x198 +-#define CODA_CMD_ENC_PARAM_HEC_MODE 0x19c +-#define CODA_RET_ENC_PARAM_CHANGE_SUCCESS 0x1c0 +- +-/* Encoder Picture Run */ +-#define CODA9_CMD_ENC_PIC_SRC_INDEX 0x180 +-#define CODA9_CMD_ENC_PIC_SRC_STRIDE 0x184 +-#define CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC 0x1a4 +-#define CODA9_CMD_ENC_PIC_SRC_ADDR_Y 0x1a8 +-#define CODA9_CMD_ENC_PIC_SRC_ADDR_CB 0x1ac +-#define CODA9_CMD_ENC_PIC_SRC_ADDR_CR 0x1b0 +-#define CODA_CMD_ENC_PIC_SRC_ADDR_Y 0x180 +-#define CODA_CMD_ENC_PIC_SRC_ADDR_CB 0x184 +-#define CODA_CMD_ENC_PIC_SRC_ADDR_CR 0x188 +-#define CODA_CMD_ENC_PIC_QS 0x18c +-#define CODA_CMD_ENC_PIC_ROT_MODE 0x190 +-#define CODA_ROT_MIR_ENABLE (1 << 4) +-#define CODA_ROT_0 (0x0 << 0) +-#define CODA_ROT_90 (0x1 << 0) +-#define CODA_ROT_180 (0x2 << 0) +-#define CODA_ROT_270 (0x3 << 0) +-#define CODA_MIR_NONE (0x0 << 2) +-#define CODA_MIR_VER (0x1 << 2) +-#define CODA_MIR_HOR (0x2 << 2) +-#define CODA_MIR_VER_HOR (0x3 << 2) +-#define CODA_CMD_ENC_PIC_OPTION 0x194 +-#define CODA_FORCE_IPICTURE BIT(1) +-#define CODA_REPORT_MB_INFO BIT(3) +-#define CODA_REPORT_MV_INFO BIT(4) +-#define CODA_REPORT_SLICE_INFO BIT(5) +-#define CODA_CMD_ENC_PIC_BB_START 0x198 +-#define CODA_CMD_ENC_PIC_BB_SIZE 0x19c +-#define CODA_RET_ENC_FRAME_NUM 0x1c0 +-#define CODA_RET_ENC_PIC_TYPE 0x1c4 +-#define CODA_RET_ENC_PIC_FRAME_IDX 0x1c8 +-#define CODA_RET_ENC_PIC_SLICE_NUM 0x1cc +-#define CODA_RET_ENC_PIC_FLAG 0x1d0 +-#define CODA_RET_ENC_PIC_SUCCESS 0x1d8 +- +-/* Set Frame Buffer */ +-#define CODA_CMD_SET_FRAME_BUF_NUM 0x180 +-#define CODA_CMD_SET_FRAME_BUF_STRIDE 0x184 +-#define CODA_CMD_SET_FRAME_SLICE_BB_START 0x188 +-#define CODA_CMD_SET_FRAME_SLICE_BB_SIZE 0x18c +-#define CODA9_CMD_SET_FRAME_SUBSAMP_A 0x188 +-#define CODA9_CMD_SET_FRAME_SUBSAMP_B 0x18c +-#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR 0x190 +-#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR 0x194 +-#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR 0x198 +-#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR 0x19c +-#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR 0x1a0 +-#define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE 0x1a4 +-#define CODA9_CMD_SET_FRAME_AXI_BTP_ADDR 0x1a4 +-#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE 0x1a8 +-#define CODA9_CMD_SET_FRAME_CACHE_SIZE 0x1a8 +-#define CODA9_CMD_SET_FRAME_CACHE_CONFIG 0x1ac +-#define CODA9_CACHE_BYPASS_OFFSET 28 +-#define CODA9_CACHE_DUALCONF_OFFSET 26 +-#define CODA9_CACHE_PAGEMERGE_OFFSET 24 +-#define CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET 16 +-#define CODA9_CACHE_CB_BUFFER_SIZE_OFFSET 8 +-#define CODA9_CACHE_CR_BUFFER_SIZE_OFFSET 0 +-#define CODA9_CMD_SET_FRAME_SUBSAMP_A_MVC 0x1b0 +-#define CODA9_CMD_SET_FRAME_SUBSAMP_B_MVC 0x1b4 +-#define CODA9_CMD_SET_FRAME_DP_BUF_BASE 0x1b0 +-#define CODA9_CMD_SET_FRAME_DP_BUF_SIZE 0x1b4 +-#define CODA9_CMD_SET_FRAME_MAX_DEC_SIZE 0x1b8 +-#define CODA9_CMD_SET_FRAME_DELAY 0x1bc +- +-/* Encoder Header */ +-#define CODA_CMD_ENC_HEADER_CODE 0x180 +-#define CODA_GAMMA_OFFSET 0 +-#define CODA_HEADER_H264_SPS 0 +-#define CODA_HEADER_H264_PPS 1 +-#define CODA_HEADER_MP4V_VOL 0 +-#define CODA_HEADER_MP4V_VOS 1 +-#define CODA_HEADER_MP4V_VIS 2 +-#define CODA9_HEADER_FRAME_CROP (1 << 3) +-#define CODA_CMD_ENC_HEADER_BB_START 0x184 +-#define CODA_CMD_ENC_HEADER_BB_SIZE 0x188 +-#define CODA9_CMD_ENC_HEADER_FRAME_CROP_H 0x18c +-#define CODA9_CMD_ENC_HEADER_FRAME_CROP_V 0x190 +- +-/* Get Version */ +-#define CODA_CMD_FIRMWARE_VERNUM 0x1c0 +-#define CODA_FIRMWARE_PRODUCT(x) (((x) >> 16) & 0xffff) +-#define CODA_FIRMWARE_MAJOR(x) (((x) >> 12) & 0x0f) +-#define CODA_FIRMWARE_MINOR(x) (((x) >> 8) & 0x0f) +-#define CODA_FIRMWARE_RELEASE(x) ((x) & 0xff) +-#define CODA_FIRMWARE_VERNUM(product, major, minor, release) \ +- ((product) << 16 | ((major) << 12) | \ +- ((minor) << 8) | (release)) +-#define CODA9_CMD_FIRMWARE_CODE_REV 0x1c4 +- +-#define CODA9_GDMA_BASE 0x1000 +-#define CODA9_GDI_CONTROL (CODA9_GDMA_BASE + 0x034) +-#define CODA9_GDI_PIC_INIT_HOST (CODA9_GDMA_BASE + 0x038) +-#define CODA9_GDI_STATUS (CODA9_GDMA_BASE + 0x080) +-#define CODA9_GDI_WPROT_ERR_CLR (CODA9_GDMA_BASE + 0x0a0) +-#define CODA9_GDI_WPROT_RGN_EN (CODA9_GDMA_BASE + 0x0ac) +- +-#define CODA9_GDI_BUS_CTRL (CODA9_GDMA_BASE + 0x0f0) +-#define CODA9_GDI_BUS_STATUS (CODA9_GDMA_BASE + 0x0f4) +- +-#define CODA9_GDI_INFO_CONTROL (CODA9_GDMA_BASE + 0x400) +-#define CODA9_GDI_INFO_PIC_SIZE (CODA9_GDMA_BASE + 0x404) +-#define CODA9_GDI_INFO_BASE_Y (CODA9_GDMA_BASE + 0x408) +-#define CODA9_GDI_INFO_BASE_CB (CODA9_GDMA_BASE + 0x40c) +-#define CODA9_GDI_INFO_BASE_CR (CODA9_GDMA_BASE + 0x410) +- +-#define CODA9_GDI_XY2_CAS_0 (CODA9_GDMA_BASE + 0x800) +-#define CODA9_GDI_XY2_CAS_F (CODA9_GDMA_BASE + 0x83c) +- +-#define CODA9_GDI_XY2_BA_0 (CODA9_GDMA_BASE + 0x840) +-#define CODA9_GDI_XY2_BA_1 (CODA9_GDMA_BASE + 0x844) +-#define CODA9_GDI_XY2_BA_2 (CODA9_GDMA_BASE + 0x848) +-#define CODA9_GDI_XY2_BA_3 (CODA9_GDMA_BASE + 0x84c) +- +-#define CODA9_GDI_XY2_RAS_0 (CODA9_GDMA_BASE + 0x850) +-#define CODA9_GDI_XY2_RAS_F (CODA9_GDMA_BASE + 0x88c) +- +-#define CODA9_GDI_XY2_RBC_CONFIG (CODA9_GDMA_BASE + 0x890) +-#define CODA9_XY2RBC_SEPARATE_MAP BIT(19) +-#define CODA9_XY2RBC_TOP_BOT_SPLIT BIT(18) +-#define CODA9_XY2RBC_TILED_MAP BIT(17) +-#define CODA9_XY2RBC_CA_INC_HOR BIT(16) +-#define CODA9_GDI_RBC2_AXI_0 (CODA9_GDMA_BASE + 0x8a0) +-#define CODA9_GDI_RBC2_AXI_1F (CODA9_GDMA_BASE + 0x91c) +-#define CODA9_GDI_TILEDBUF_BASE (CODA9_GDMA_BASE + 0x920) +- +-#define CODA9_JPEG_BASE 0x3000 +-#define CODA9_REG_JPEG_PIC_START (CODA9_JPEG_BASE + 0x000) +-#define CODA9_REG_JPEG_PIC_STATUS (CODA9_JPEG_BASE + 0x004) +-#define CODA9_JPEG_STATUS_OVERFLOW BIT(3) +-#define CODA9_JPEG_STATUS_BBC_INT BIT(2) +-#define CODA9_JPEG_STATUS_ERROR BIT(1) +-#define CODA9_JPEG_STATUS_DONE BIT(0) +-#define CODA9_REG_JPEG_PIC_ERRMB (CODA9_JPEG_BASE + 0x008) +-#define CODA9_JPEG_ERRMB_RESTART_IDX_MASK (0xf << 24) +-#define CODA9_JPEG_ERRMB_MCU_POS_X_MASK (0xfff << 12) +-#define CODA9_JPEG_ERRMB_MCU_POS_Y_MASK 0xfff +-#define CODA9_REG_JPEG_PIC_CTRL (CODA9_JPEG_BASE + 0x010) +-#define CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN BIT(6) +-#define CODA9_JPEG_PIC_CTRL_TC_DIRECTION BIT(4) +-#define CODA9_JPEG_PIC_CTRL_ENCODER_EN BIT(3) +-#define CODA9_REG_JPEG_PIC_SIZE (CODA9_JPEG_BASE + 0x014) +-#define CODA9_REG_JPEG_MCU_INFO (CODA9_JPEG_BASE + 0x018) +-#define CODA9_JPEG_MCU_BLOCK_NUM_OFFSET 16 +-#define CODA9_JPEG_COMP_NUM_OFFSET 12 +-#define CODA9_JPEG_COMP0_INFO_OFFSET 8 +-#define CODA9_JPEG_COMP1_INFO_OFFSET 4 +-#define CODA9_JPEG_COMP2_INFO_OFFSET 0 +-#define CODA9_REG_JPEG_ROT_INFO (CODA9_JPEG_BASE + 0x01c) +-#define CODA9_JPEG_ROT_MIR_ENABLE BIT(4) +-#define CODA9_JPEG_ROT_MIR_MODE_MASK 0xf +-#define CODA9_REG_JPEG_SCL_INFO (CODA9_JPEG_BASE + 0x020) +-#define CODA9_JPEG_SCL_ENABLE BIT(4) +-#define CODA9_JPEG_SCL_HOR_MODE_MASK (0x3 << 2) +-#define CODA9_JPEG_SCL_VER_MODE_MASK (0x3 << 0) +-#define CODA9_REG_JPEG_IF_INFO (CODA9_JPEG_BASE + 0x024) +-#define CODA9_JPEG_SENS_IF_CLR BIT(1) +-#define CODA9_JPEG_DISP_IF_CLR BIT(0) +-#define CODA9_REG_JPEG_OP_INFO (CODA9_JPEG_BASE + 0x02c) +-#define CODA9_JPEG_BUS_REQ_NUM_OFFSET 0 +-#define CODA9_JPEG_BUS_REQ_NUM_MASK 0x7 +-#define CODA9_REG_JPEG_DPB_CONFIG (CODA9_JPEG_BASE + 0x030) +-#define CODA9_REG_JPEG_DPB_BASE00 (CODA9_JPEG_BASE + 0x040) +-#define CODA9_REG_JPEG_HUFF_CTRL (CODA9_JPEG_BASE + 0x080) +-#define CODA9_REG_JPEG_HUFF_ADDR (CODA9_JPEG_BASE + 0x084) +-#define CODA9_REG_JPEG_HUFF_DATA (CODA9_JPEG_BASE + 0x088) +-#define CODA9_REG_JPEG_QMAT_CTRL (CODA9_JPEG_BASE + 0x090) +-#define CODA9_REG_JPEG_QMAT_ADDR (CODA9_JPEG_BASE + 0x094) +-#define CODA9_REG_JPEG_QMAT_DATA (CODA9_JPEG_BASE + 0x098) +-#define CODA9_REG_JPEG_RST_INTVAL (CODA9_JPEG_BASE + 0x0b0) +-#define CODA9_REG_JPEG_RST_INDEX (CODA9_JPEG_BASE + 0x0b4) +-#define CODA9_REG_JPEG_RST_COUNT (CODA9_JPEG_BASE + 0x0b8) +-#define CODA9_REG_JPEG_DPCM_DIFF_Y (CODA9_JPEG_BASE + 0x0f0) +-#define CODA9_REG_JPEG_DPCM_DIFF_CB (CODA9_JPEG_BASE + 0x0f4) +-#define CODA9_REG_JPEG_DPCM_DIFF_CR (CODA9_JPEG_BASE + 0x0f8) +-#define CODA9_REG_JPEG_GBU_CTRL (CODA9_JPEG_BASE + 0x100) +-#define CODA9_REG_JPEG_GBU_BT_PTR (CODA9_JPEG_BASE + 0x110) +-#define CODA9_REG_JPEG_GBU_WD_PTR (CODA9_JPEG_BASE + 0x114) +-#define CODA9_REG_JPEG_GBU_TT_CNT (CODA9_JPEG_BASE + 0x118) +-#define CODA9_REG_JPEG_GBU_BBSR (CODA9_JPEG_BASE + 0x140) +-#define CODA9_REG_JPEG_GBU_BBER (CODA9_JPEG_BASE + 0x144) +-#define CODA9_REG_JPEG_GBU_BBIR (CODA9_JPEG_BASE + 0x148) +-#define CODA9_REG_JPEG_GBU_BBHR (CODA9_JPEG_BASE + 0x14c) +-#define CODA9_REG_JPEG_GBU_BCNT (CODA9_JPEG_BASE + 0x158) +-#define CODA9_REG_JPEG_GBU_FF_RPTR (CODA9_JPEG_BASE + 0x160) +-#define CODA9_REG_JPEG_GBU_FF_WPTR (CODA9_JPEG_BASE + 0x164) +-#define CODA9_REG_JPEG_BBC_END_ADDR (CODA9_JPEG_BASE + 0x208) +-#define CODA9_REG_JPEG_BBC_WR_PTR (CODA9_JPEG_BASE + 0x20c) +-#define CODA9_REG_JPEG_BBC_RD_PTR (CODA9_JPEG_BASE + 0x210) +-#define CODA9_REG_JPEG_BBC_EXT_ADDR (CODA9_JPEG_BASE + 0x214) +-#define CODA9_REG_JPEG_BBC_INT_ADDR (CODA9_JPEG_BASE + 0x218) +-#define CODA9_REG_JPEG_BBC_DATA_CNT (CODA9_JPEG_BASE + 0x21c) +-#define CODA9_REG_JPEG_BBC_COMMAND (CODA9_JPEG_BASE + 0x220) +-#define CODA9_REG_JPEG_BBC_BUSY (CODA9_JPEG_BASE + 0x224) +-#define CODA9_REG_JPEG_BBC_CTRL (CODA9_JPEG_BASE + 0x228) +-#define CODA9_REG_JPEG_BBC_CUR_POS (CODA9_JPEG_BASE + 0x22c) +-#define CODA9_REG_JPEG_BBC_BAS_ADDR (CODA9_JPEG_BASE + 0x230) +-#define CODA9_REG_JPEG_BBC_STRM_CTRL (CODA9_JPEG_BASE + 0x234) +-#define CODA9_REG_JPEG_BBC_FLUSH_CMD (CODA9_JPEG_BASE + 0x238) +- +-#endif +diff -Naur --no-dereference a/drivers/media/platform/chips-media/imx-vdoa.c b/drivers/media/platform/chips-media/imx-vdoa.c +--- a/drivers/media/platform/chips-media/imx-vdoa.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/imx-vdoa.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,346 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * i.MX6 Video Data Order Adapter (VDOA) +- * +- * Copyright (C) 2014 Philipp Zabel +- * Copyright (C) 2016 Pengutronix, Michael Tretter +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "imx-vdoa.h" +- +-#define VDOA_NAME "imx-vdoa" +- +-#define VDOAC 0x00 +-#define VDOASRR 0x04 +-#define VDOAIE 0x08 +-#define VDOAIST 0x0c +-#define VDOAFP 0x10 +-#define VDOAIEBA00 0x14 +-#define VDOAIEBA01 0x18 +-#define VDOAIEBA02 0x1c +-#define VDOAIEBA10 0x20 +-#define VDOAIEBA11 0x24 +-#define VDOAIEBA12 0x28 +-#define VDOASL 0x2c +-#define VDOAIUBO 0x30 +-#define VDOAVEBA0 0x34 +-#define VDOAVEBA1 0x38 +-#define VDOAVEBA2 0x3c +-#define VDOAVUBO 0x40 +-#define VDOASR 0x44 +- +-#define VDOAC_ISEL BIT(6) +-#define VDOAC_PFS BIT(5) +-#define VDOAC_SO BIT(4) +-#define VDOAC_SYNC BIT(3) +-#define VDOAC_NF BIT(2) +-#define VDOAC_BNDM_MASK 0x3 +-#define VDOAC_BAND_HEIGHT_8 0x0 +-#define VDOAC_BAND_HEIGHT_16 0x1 +-#define VDOAC_BAND_HEIGHT_32 0x2 +- +-#define VDOASRR_START BIT(1) +-#define VDOASRR_SWRST BIT(0) +- +-#define VDOAIE_EITERR BIT(1) +-#define VDOAIE_EIEOT BIT(0) +- +-#define VDOAIST_TERR BIT(1) +-#define VDOAIST_EOT BIT(0) +- +-#define VDOAFP_FH_MASK (0x1fff << 16) +-#define VDOAFP_FW_MASK (0x3fff) +- +-#define VDOASL_VSLY_MASK (0x3fff << 16) +-#define VDOASL_ISLY_MASK (0x7fff) +- +-#define VDOASR_ERRW BIT(4) +-#define VDOASR_EOB BIT(3) +-#define VDOASR_CURRENT_FRAME (0x3 << 1) +-#define VDOASR_CURRENT_BUFFER BIT(1) +- +-enum { +- V4L2_M2M_SRC = 0, +- V4L2_M2M_DST = 1, +-}; +- +-struct vdoa_data { +- struct vdoa_ctx *curr_ctx; +- struct device *dev; +- struct clk *vdoa_clk; +- void __iomem *regs; +-}; +- +-struct vdoa_q_data { +- unsigned int width; +- unsigned int height; +- unsigned int bytesperline; +- unsigned int sizeimage; +- u32 pixelformat; +-}; +- +-struct vdoa_ctx { +- struct vdoa_data *vdoa; +- struct completion completion; +- struct vdoa_q_data q_data[2]; +- unsigned int submitted_job; +- unsigned int completed_job; +-}; +- +-static irqreturn_t vdoa_irq_handler(int irq, void *data) +-{ +- struct vdoa_data *vdoa = data; +- struct vdoa_ctx *curr_ctx; +- u32 val; +- +- /* Disable interrupts */ +- writel(0, vdoa->regs + VDOAIE); +- +- curr_ctx = vdoa->curr_ctx; +- if (!curr_ctx) { +- dev_warn(vdoa->dev, +- "Instance released before the end of transaction\n"); +- return IRQ_HANDLED; +- } +- +- val = readl(vdoa->regs + VDOAIST); +- writel(val, vdoa->regs + VDOAIST); +- if (val & VDOAIST_TERR) { +- val = readl(vdoa->regs + VDOASR) & VDOASR_ERRW; +- dev_err(vdoa->dev, "AXI %s error\n", val ? "write" : "read"); +- } else if (!(val & VDOAIST_EOT)) { +- dev_warn(vdoa->dev, "Spurious interrupt\n"); +- } +- curr_ctx->completed_job++; +- complete(&curr_ctx->completion); +- +- return IRQ_HANDLED; +-} +- +-int vdoa_wait_for_completion(struct vdoa_ctx *ctx) +-{ +- struct vdoa_data *vdoa = ctx->vdoa; +- +- if (ctx->submitted_job == ctx->completed_job) +- return 0; +- +- if (!wait_for_completion_timeout(&ctx->completion, +- msecs_to_jiffies(300))) { +- dev_err(vdoa->dev, +- "Timeout waiting for transfer result\n"); +- return -ETIMEDOUT; +- } +- +- return 0; +-} +-EXPORT_SYMBOL(vdoa_wait_for_completion); +- +-void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src) +-{ +- struct vdoa_q_data *src_q_data, *dst_q_data; +- struct vdoa_data *vdoa = ctx->vdoa; +- u32 val; +- +- if (vdoa->curr_ctx) +- vdoa_wait_for_completion(vdoa->curr_ctx); +- +- vdoa->curr_ctx = ctx; +- +- reinit_completion(&ctx->completion); +- ctx->submitted_job++; +- +- src_q_data = &ctx->q_data[V4L2_M2M_SRC]; +- dst_q_data = &ctx->q_data[V4L2_M2M_DST]; +- +- /* Progressive, no sync, 1 frame per run */ +- if (dst_q_data->pixelformat == V4L2_PIX_FMT_YUYV) +- val = VDOAC_PFS; +- else +- val = 0; +- writel(val, vdoa->regs + VDOAC); +- +- writel(dst_q_data->height << 16 | dst_q_data->width, +- vdoa->regs + VDOAFP); +- +- val = dst; +- writel(val, vdoa->regs + VDOAIEBA00); +- +- writel(src_q_data->bytesperline << 16 | dst_q_data->bytesperline, +- vdoa->regs + VDOASL); +- +- if (dst_q_data->pixelformat == V4L2_PIX_FMT_NV12 || +- dst_q_data->pixelformat == V4L2_PIX_FMT_NV21) +- val = dst_q_data->bytesperline * dst_q_data->height; +- else +- val = 0; +- writel(val, vdoa->regs + VDOAIUBO); +- +- val = src; +- writel(val, vdoa->regs + VDOAVEBA0); +- val = round_up(src_q_data->bytesperline * src_q_data->height, 4096); +- writel(val, vdoa->regs + VDOAVUBO); +- +- /* Enable interrupts and start transfer */ +- writel(VDOAIE_EITERR | VDOAIE_EIEOT, vdoa->regs + VDOAIE); +- writel(VDOASRR_START, vdoa->regs + VDOASRR); +-} +-EXPORT_SYMBOL(vdoa_device_run); +- +-struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa) +-{ +- struct vdoa_ctx *ctx; +- int err; +- +- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); +- if (!ctx) +- return NULL; +- +- err = clk_prepare_enable(vdoa->vdoa_clk); +- if (err) { +- kfree(ctx); +- return NULL; +- } +- +- init_completion(&ctx->completion); +- ctx->vdoa = vdoa; +- +- return ctx; +-} +-EXPORT_SYMBOL(vdoa_context_create); +- +-void vdoa_context_destroy(struct vdoa_ctx *ctx) +-{ +- struct vdoa_data *vdoa = ctx->vdoa; +- +- if (vdoa->curr_ctx == ctx) { +- vdoa_wait_for_completion(vdoa->curr_ctx); +- vdoa->curr_ctx = NULL; +- } +- +- clk_disable_unprepare(vdoa->vdoa_clk); +- kfree(ctx); +-} +-EXPORT_SYMBOL(vdoa_context_destroy); +- +-int vdoa_context_configure(struct vdoa_ctx *ctx, +- unsigned int width, unsigned int height, +- u32 pixelformat) +-{ +- struct vdoa_q_data *src_q_data; +- struct vdoa_q_data *dst_q_data; +- +- if (width < 16 || width > 8192 || width % 16 != 0 || +- height < 16 || height > 4096 || height % 16 != 0) +- return -EINVAL; +- +- if (pixelformat != V4L2_PIX_FMT_YUYV && +- pixelformat != V4L2_PIX_FMT_NV12) +- return -EINVAL; +- +- /* If no context is passed, only check if the format is valid */ +- if (!ctx) +- return 0; +- +- src_q_data = &ctx->q_data[V4L2_M2M_SRC]; +- dst_q_data = &ctx->q_data[V4L2_M2M_DST]; +- +- src_q_data->width = width; +- src_q_data->height = height; +- src_q_data->bytesperline = width; +- src_q_data->sizeimage = +- round_up(src_q_data->bytesperline * height, 4096) + +- src_q_data->bytesperline * height / 2; +- +- dst_q_data->width = width; +- dst_q_data->height = height; +- dst_q_data->pixelformat = pixelformat; +- switch (pixelformat) { +- case V4L2_PIX_FMT_YUYV: +- dst_q_data->bytesperline = width * 2; +- dst_q_data->sizeimage = dst_q_data->bytesperline * height; +- break; +- case V4L2_PIX_FMT_NV12: +- default: +- dst_q_data->bytesperline = width; +- dst_q_data->sizeimage = +- dst_q_data->bytesperline * height * 3 / 2; +- break; +- } +- +- return 0; +-} +-EXPORT_SYMBOL(vdoa_context_configure); +- +-static int vdoa_probe(struct platform_device *pdev) +-{ +- struct vdoa_data *vdoa; +- int ret; +- +- ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); +- if (ret) { +- dev_err(&pdev->dev, "DMA enable failed\n"); +- return ret; +- } +- +- vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL); +- if (!vdoa) +- return -ENOMEM; +- +- vdoa->dev = &pdev->dev; +- +- vdoa->vdoa_clk = devm_clk_get(vdoa->dev, NULL); +- if (IS_ERR(vdoa->vdoa_clk)) { +- dev_err(vdoa->dev, "Failed to get clock\n"); +- return PTR_ERR(vdoa->vdoa_clk); +- } +- +- vdoa->regs = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(vdoa->regs)) +- return PTR_ERR(vdoa->regs); +- +- ret = platform_get_irq(pdev, 0); +- if (ret < 0) +- return ret; +- ret = devm_request_threaded_irq(&pdev->dev, ret, NULL, +- vdoa_irq_handler, IRQF_ONESHOT, +- "vdoa", vdoa); +- if (ret < 0) { +- dev_err(vdoa->dev, "Failed to get irq\n"); +- return ret; +- } +- +- platform_set_drvdata(pdev, vdoa); +- +- return 0; +-} +- +-static const struct of_device_id vdoa_dt_ids[] = { +- { .compatible = "fsl,imx6q-vdoa" }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, vdoa_dt_ids); +- +-static struct platform_driver vdoa_driver = { +- .probe = vdoa_probe, +- .driver = { +- .name = VDOA_NAME, +- .of_match_table = vdoa_dt_ids, +- }, +-}; +- +-module_platform_driver(vdoa_driver); +- +-MODULE_DESCRIPTION("Video Data Order Adapter"); +-MODULE_AUTHOR("Philipp Zabel "); +-MODULE_ALIAS("platform:imx-vdoa"); +-MODULE_LICENSE("GPL"); +diff -Naur --no-dereference a/drivers/media/platform/chips-media/imx-vdoa.h b/drivers/media/platform/chips-media/imx-vdoa.h +--- a/drivers/media/platform/chips-media/imx-vdoa.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/imx-vdoa.h 1969-12-31 19:00:00.000000000 -0500 +@@ -1,50 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-or-later */ +-/* +- * Copyright (C) 2016 Pengutronix +- */ +- +-#ifndef IMX_VDOA_H +-#define IMX_VDOA_H +- +-struct vdoa_data; +-struct vdoa_ctx; +- +-#if (defined CONFIG_VIDEO_IMX_VDOA || defined CONFIG_VIDEO_IMX_VDOA_MODULE) +- +-struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa); +-int vdoa_context_configure(struct vdoa_ctx *ctx, +- unsigned int width, unsigned int height, +- u32 pixelformat); +-void vdoa_context_destroy(struct vdoa_ctx *ctx); +- +-void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src); +-int vdoa_wait_for_completion(struct vdoa_ctx *ctx); +- +-#else +- +-static inline struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa) +-{ +- return NULL; +-} +- +-static inline int vdoa_context_configure(struct vdoa_ctx *ctx, +- unsigned int width, +- unsigned int height, +- u32 pixelformat) +-{ +- return 0; +-} +- +-static inline void vdoa_context_destroy(struct vdoa_ctx *ctx) { }; +- +-static inline void vdoa_device_run(struct vdoa_ctx *ctx, +- dma_addr_t dst, dma_addr_t src) { }; +- +-static inline int vdoa_wait_for_completion(struct vdoa_ctx *ctx) +-{ +- return 0; +-}; +- +-#endif +- +-#endif /* IMX_VDOA_H */ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/Kconfig b/drivers/media/platform/chips-media/Kconfig +--- a/drivers/media/platform/chips-media/Kconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/Kconfig 2024-03-28 11:26:09.897017444 -0400 +@@ -2,19 +2,5 @@ + + comment "Chips&Media media platform drivers" + +-config VIDEO_CODA +- tristate "Chips&Media Coda multi-standard codec IP" +- depends on V4L_MEM2MEM_DRIVERS +- depends on VIDEO_DEV && OF && (ARCH_MXC || COMPILE_TEST) +- select SRAM +- select VIDEOBUF2_DMA_CONTIG +- select VIDEOBUF2_VMALLOC +- select V4L2_JPEG_HELPER +- select V4L2_MEM2MEM_DEV +- select GENERIC_ALLOCATOR +- help +- Coda is a range of video codec IPs that supports +- H.264, MPEG-4, and other video formats. +- +-config VIDEO_IMX_VDOA +- def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST ++source "drivers/media/platform/chips-media/coda/Kconfig" ++source "drivers/media/platform/chips-media/wave5/Kconfig" +diff -Naur --no-dereference a/drivers/media/platform/chips-media/Makefile b/drivers/media/platform/chips-media/Makefile +--- a/drivers/media/platform/chips-media/Makefile 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/Makefile 2024-03-28 11:26:09.897017444 -0400 +@@ -1,6 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only + +-coda-vpu-objs := coda-common.o coda-bit.o coda-gdi.o coda-h264.o coda-mpeg2.o coda-mpeg4.o coda-jpeg.o +- +-obj-$(CONFIG_VIDEO_CODA) += coda-vpu.o +-obj-$(CONFIG_VIDEO_IMX_VDOA) += imx-vdoa.o ++obj-y += coda/ ++obj-y += wave5/ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/trace.h b/drivers/media/platform/chips-media/trace.h +--- a/drivers/media/platform/chips-media/trace.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/chips-media/trace.h 1969-12-31 19:00:00.000000000 -0500 +@@ -1,175 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-#undef TRACE_SYSTEM +-#define TRACE_SYSTEM coda +- +-#if !defined(__CODA_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) +-#define __CODA_TRACE_H__ +- +-#include +-#include +- +-#include "coda.h" +- +-TRACE_EVENT(coda_bit_run, +- TP_PROTO(struct coda_ctx *ctx, int cmd), +- +- TP_ARGS(ctx, cmd), +- +- TP_STRUCT__entry( +- __field(int, minor) +- __field(int, ctx) +- __field(int, cmd) +- ), +- +- TP_fast_assign( +- __entry->minor = ctx->fh.vdev->minor; +- __entry->ctx = ctx->idx; +- __entry->cmd = cmd; +- ), +- +- TP_printk("minor = %d, ctx = %d, cmd = %d", +- __entry->minor, __entry->ctx, __entry->cmd) +-); +- +-TRACE_EVENT(coda_bit_done, +- TP_PROTO(struct coda_ctx *ctx), +- +- TP_ARGS(ctx), +- +- TP_STRUCT__entry( +- __field(int, minor) +- __field(int, ctx) +- ), +- +- TP_fast_assign( +- __entry->minor = ctx->fh.vdev->minor; +- __entry->ctx = ctx->idx; +- ), +- +- TP_printk("minor = %d, ctx = %d", __entry->minor, __entry->ctx) +-); +- +-DECLARE_EVENT_CLASS(coda_buf_class, +- TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), +- +- TP_ARGS(ctx, buf), +- +- TP_STRUCT__entry( +- __field(int, minor) +- __field(int, index) +- __field(int, ctx) +- ), +- +- TP_fast_assign( +- __entry->minor = ctx->fh.vdev->minor; +- __entry->index = buf->vb2_buf.index; +- __entry->ctx = ctx->idx; +- ), +- +- TP_printk("minor = %d, index = %d, ctx = %d", +- __entry->minor, __entry->index, __entry->ctx) +-); +- +-DEFINE_EVENT(coda_buf_class, coda_enc_pic_run, +- TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), +- TP_ARGS(ctx, buf) +-); +- +-DEFINE_EVENT(coda_buf_class, coda_enc_pic_done, +- TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), +- TP_ARGS(ctx, buf) +-); +- +-DECLARE_EVENT_CLASS(coda_buf_meta_class, +- TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, +- struct coda_buffer_meta *meta), +- +- TP_ARGS(ctx, buf, meta), +- +- TP_STRUCT__entry( +- __field(int, minor) +- __field(int, index) +- __field(int, start) +- __field(int, end) +- __field(int, ctx) +- ), +- +- TP_fast_assign( +- __entry->minor = ctx->fh.vdev->minor; +- __entry->index = buf->vb2_buf.index; +- __entry->start = meta->start & ctx->bitstream_fifo.kfifo.mask; +- __entry->end = meta->end & ctx->bitstream_fifo.kfifo.mask; +- __entry->ctx = ctx->idx; +- ), +- +- TP_printk("minor = %d, index = %d, start = 0x%x, end = 0x%x, ctx = %d", +- __entry->minor, __entry->index, __entry->start, __entry->end, +- __entry->ctx) +-); +- +-DEFINE_EVENT(coda_buf_meta_class, coda_bit_queue, +- TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, +- struct coda_buffer_meta *meta), +- TP_ARGS(ctx, buf, meta) +-); +- +-DECLARE_EVENT_CLASS(coda_meta_class, +- TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta), +- +- TP_ARGS(ctx, meta), +- +- TP_STRUCT__entry( +- __field(int, minor) +- __field(int, start) +- __field(int, end) +- __field(int, ctx) +- ), +- +- TP_fast_assign( +- __entry->minor = ctx->fh.vdev->minor; +- __entry->start = meta ? (meta->start & +- ctx->bitstream_fifo.kfifo.mask) : 0; +- __entry->end = meta ? (meta->end & +- ctx->bitstream_fifo.kfifo.mask) : 0; +- __entry->ctx = ctx->idx; +- ), +- +- TP_printk("minor = %d, start = 0x%x, end = 0x%x, ctx = %d", +- __entry->minor, __entry->start, __entry->end, __entry->ctx) +-); +- +-DEFINE_EVENT(coda_meta_class, coda_dec_pic_run, +- TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta), +- TP_ARGS(ctx, meta) +-); +- +-DEFINE_EVENT(coda_meta_class, coda_dec_pic_done, +- TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta), +- TP_ARGS(ctx, meta) +-); +- +-DEFINE_EVENT(coda_buf_meta_class, coda_dec_rot_done, +- TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf, +- struct coda_buffer_meta *meta), +- TP_ARGS(ctx, buf, meta) +-); +- +-DEFINE_EVENT(coda_buf_class, coda_jpeg_run, +- TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), +- TP_ARGS(ctx, buf) +-); +- +-DEFINE_EVENT(coda_buf_class, coda_jpeg_done, +- TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf), +- TP_ARGS(ctx, buf) +-); +- +-#endif /* __CODA_TRACE_H__ */ +- +-#undef TRACE_INCLUDE_PATH +-#define TRACE_INCLUDE_PATH ../../drivers/media/platform/chips-media +-#undef TRACE_INCLUDE_FILE +-#define TRACE_INCLUDE_FILE trace +- +-/* This part must be outside protection */ +-#include +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/Kconfig b/drivers/media/platform/chips-media/wave5/Kconfig +--- a/drivers/media/platform/chips-media/wave5/Kconfig 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/Kconfig 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: GPL-2.0 ++config VIDEO_WAVE_VPU ++ tristate "Chips&Media Wave Codec Driver" ++ depends on VIDEO_DEV ++ select VIDEOBUF2_DMA_CONTIG ++ select VIDEOBUF2_VMALLOC ++ select V4L2_MEM2MEM_DEV ++ help ++ Chips&Media stateful encoder and decoder driver. ++ The driver supports HEVC and H264 formats. ++ To compile this driver as modules, choose M here: the ++ modules will be called wave5. +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/Makefile b/drivers/media/platform/chips-media/wave5/Makefile +--- a/drivers/media/platform/chips-media/wave5/Makefile 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/Makefile 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,10 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-$(CONFIG_VIDEO_WAVE_VPU) += wave5.o ++wave5-objs += wave5-hw.o \ ++ wave5-vpuapi.o \ ++ wave5-vdi.o \ ++ wave5-vpu-dec.o \ ++ wave5-vpu.o \ ++ wave5-vpu-enc.o \ ++ wave5-helper.o +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5.h b/drivers/media/platform/chips-media/wave5/wave5.h +--- a/drivers/media/platform/chips-media/wave5/wave5.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,114 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ ++/* ++ * Wave5 series multi-standard codec IP - wave5 backend definitions ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#ifndef __WAVE5_FUNCTION_H__ ++#define __WAVE5_FUNCTION_H__ ++ ++#define WAVE5_SUBSAMPLED_ONE_SIZE(_w, _h) (ALIGN((_w) / 4, 16) * ALIGN((_h) / 4, 8)) ++#define WAVE5_SUBSAMPLED_ONE_SIZE_AVC(_w, _h) (ALIGN((_w) / 4, 32) * ALIGN((_h) / 4, 4)) ++ ++/* ++ * Bitstream buffer option: Explicit End ++ * When set to 1 the VPU assumes that the bitstream has at least one frame and ++ * will read until the end of the bitstream buffer. ++ * When set to 0 the VPU will not read the last few bytes. ++ * This option can be set anytime but cannot be cleared during processing. ++ * It can be set to force finish decoding even though there is not enough ++ * bitstream data for a full frame. ++ */ ++#define BSOPTION_ENABLE_EXPLICIT_END BIT(0) ++#define BSOPTION_HIGHLIGHT_STREAM_END BIT(1) ++ ++/* ++ * Currently the driver only supports hardware with little endian but for source ++ * picture format, the bitstream and the report parameter the hardware works ++ * with the opposite endianness, thus hard-code big endian for the register ++ * writes ++ */ ++#define PIC_SRC_ENDIANNESS_BIG_ENDIAN 0xf ++#define BITSTREAM_ENDIANNESS_BIG_ENDIAN 0xf ++#define REPORT_PARAM_ENDIANNESS_BIG_ENDIAN 0xf ++ ++#define WTL_RIGHT_JUSTIFIED 0 ++#define WTL_LEFT_JUSTIFIED 1 ++#define WTL_PIXEL_8BIT 0 ++#define WTL_PIXEL_16BIT 1 ++#define WTL_PIXEL_32BIT 2 ++ ++/* Mirror & rotation modes of the PRP (pre-processing) module */ ++#define NONE_ROTATE 0x0 ++#define ROT_CLOCKWISE_90 0x3 ++#define ROT_CLOCKWISE_180 0x5 ++#define ROT_CLOCKWISE_270 0x7 ++#define MIR_HOR_FLIP 0x11 ++#define MIR_VER_FLIP 0x9 ++#define MIR_HOR_VER_FLIP (MIR_HOR_FLIP | MIR_VER_FLIP) ++ ++bool wave5_vpu_is_init(struct vpu_device *vpu_dev); ++ ++unsigned int wave5_vpu_get_product_id(struct vpu_device *vpu_dev); ++ ++int wave5_vpu_get_version(struct vpu_device *vpu_dev, u32 *revision); ++ ++int wave5_vpu_init(struct device *dev, u8 *fw, size_t size); ++ ++int wave5_vpu_reset(struct device *dev, enum sw_reset_mode reset_mode); ++ ++int wave5_vpu_build_up_dec_param(struct vpu_instance *inst, struct dec_open_param *param); ++ ++int wave5_vpu_dec_set_bitstream_flag(struct vpu_instance *inst, bool eos); ++ ++int wave5_vpu_hw_flush_instance(struct vpu_instance *inst); ++ ++int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, ++ struct frame_buffer *fb_arr, enum tiled_map_type map_type, ++ unsigned int count); ++ ++int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size); ++ ++int wave5_vpu_dec_init_seq(struct vpu_instance *inst); ++ ++int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct dec_initial_info *info); ++ ++int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res); ++ ++int wave5_vpu_dec_get_result(struct vpu_instance *inst, struct dec_output_info *result); ++ ++int wave5_vpu_dec_finish_seq(struct vpu_instance *inst, u32 *fail_res); ++ ++int wave5_dec_clr_disp_flag(struct vpu_instance *inst, unsigned int index); ++ ++int wave5_dec_set_disp_flag(struct vpu_instance *inst, unsigned int index); ++ ++int wave5_vpu_clear_interrupt(struct vpu_instance *inst, u32 flags); ++ ++dma_addr_t wave5_dec_get_rd_ptr(struct vpu_instance *inst); ++ ++int wave5_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr); ++ ++/***< WAVE5 encoder >******/ ++ ++int wave5_vpu_build_up_enc_param(struct device *dev, struct vpu_instance *inst, ++ struct enc_open_param *open_param); ++ ++int wave5_vpu_enc_init_seq(struct vpu_instance *inst); ++ ++int wave5_vpu_enc_get_seq_info(struct vpu_instance *inst, struct enc_initial_info *info); ++ ++int wave5_vpu_enc_register_framebuffer(struct device *dev, struct vpu_instance *inst, ++ struct frame_buffer *fb_arr, enum tiled_map_type map_type, ++ unsigned int count); ++ ++int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res); ++ ++int wave5_vpu_enc_get_result(struct vpu_instance *inst, struct enc_output_info *result); ++ ++int wave5_vpu_enc_finish_seq(struct vpu_instance *inst, u32 *fail_res); ++ ++int wave5_vpu_enc_check_open_param(struct vpu_instance *inst, struct enc_open_param *open_param); ++ ++#endif /* __WAVE5_FUNCTION_H__ */ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-helper.c b/drivers/media/platform/chips-media/wave5/wave5-helper.c +--- a/drivers/media/platform/chips-media/wave5/wave5-helper.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-helper.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,213 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) ++/* ++ * Wave5 series multi-standard codec IP - decoder interface ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#include "wave5-helper.h" ++ ++const char *state_to_str(enum vpu_instance_state state) ++{ ++ switch (state) { ++ case VPU_INST_STATE_NONE: ++ return "NONE"; ++ case VPU_INST_STATE_OPEN: ++ return "OPEN"; ++ case VPU_INST_STATE_INIT_SEQ: ++ return "INIT_SEQ"; ++ case VPU_INST_STATE_PIC_RUN: ++ return "PIC_RUN"; ++ case VPU_INST_STATE_STOP: ++ return "STOP"; ++ default: ++ return "UNKNOWN"; ++ } ++} ++ ++void wave5_cleanup_instance(struct vpu_instance *inst) ++{ ++ int i; ++ ++ if (list_is_singular(&inst->list)) ++ wave5_vdi_free_sram(inst->dev); ++ ++ for (i = 0; i < inst->fbc_buf_count; i++) ++ wave5_vpu_dec_reset_framebuffer(inst, i); ++ ++ wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf); ++ v4l2_ctrl_handler_free(&inst->v4l2_ctrl_hdl); ++ if (inst->v4l2_fh.vdev) { ++ v4l2_fh_del(&inst->v4l2_fh); ++ v4l2_fh_exit(&inst->v4l2_fh); ++ } ++ list_del_init(&inst->list); ++ ida_free(&inst->dev->inst_ida, inst->id); ++ kfree(inst->codec_info); ++ kfree(inst); ++} ++ ++int wave5_vpu_release_device(struct file *filp, ++ int (*close_func)(struct vpu_instance *inst, u32 *fail_res), ++ char *name) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(filp->private_data); ++ ++ v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx); ++ if (inst->state != VPU_INST_STATE_NONE) { ++ u32 fail_res; ++ int ret; ++ ++ ret = close_func(inst, &fail_res); ++ if (fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING) { ++ dev_err(inst->dev->dev, "%s close failed, device is still running\n", ++ name); ++ return -EBUSY; ++ } ++ if (ret && ret != -EIO) { ++ dev_err(inst->dev->dev, "%s close, fail: %d\n", name, ret); ++ return ret; ++ } ++ } ++ ++ wave5_cleanup_instance(inst); ++ ++ return 0; ++} ++ ++int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq, ++ const struct vb2_ops *ops) ++{ ++ struct vpu_instance *inst = priv; ++ int ret; ++ ++ src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; ++ src_vq->io_modes = VB2_MMAP | VB2_DMABUF; ++ src_vq->mem_ops = &vb2_dma_contig_memops; ++ src_vq->ops = ops; ++ src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ src_vq->buf_struct_size = sizeof(struct vpu_src_buffer); ++ src_vq->drv_priv = inst; ++ src_vq->lock = &inst->dev->dev_lock; ++ src_vq->dev = inst->dev->v4l2_dev.dev; ++ ret = vb2_queue_init(src_vq); ++ if (ret) ++ return ret; ++ ++ dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; ++ dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; ++ dst_vq->mem_ops = &vb2_dma_contig_memops; ++ dst_vq->ops = ops; ++ dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; ++ dst_vq->buf_struct_size = sizeof(struct vpu_src_buffer); ++ dst_vq->drv_priv = inst; ++ dst_vq->lock = &inst->dev->dev_lock; ++ dst_vq->dev = inst->dev->v4l2_dev.dev; ++ ret = vb2_queue_init(dst_vq); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ bool is_decoder = inst->type == VPU_INST_TYPE_DEC; ++ ++ dev_dbg(inst->dev->dev, "%s: [%s] type: %u id: %u | flags: %u\n", __func__, ++ is_decoder ? "decoder" : "encoder", sub->type, sub->id, sub->flags); ++ ++ switch (sub->type) { ++ case V4L2_EVENT_EOS: ++ return v4l2_event_subscribe(fh, sub, 0, NULL); ++ case V4L2_EVENT_SOURCE_CHANGE: ++ if (is_decoder) ++ return v4l2_src_change_event_subscribe(fh, sub); ++ return -EINVAL; ++ case V4L2_EVENT_CTRL: ++ return v4l2_ctrl_subscribe_event(fh, sub); ++ default: ++ return -EINVAL; ++ } ++} ++ ++int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ int i; ++ ++ f->fmt.pix_mp.width = inst->src_fmt.width; ++ f->fmt.pix_mp.height = inst->src_fmt.height; ++ f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat; ++ f->fmt.pix_mp.field = inst->src_fmt.field; ++ f->fmt.pix_mp.flags = inst->src_fmt.flags; ++ f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes; ++ for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { ++ f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->src_fmt.plane_fmt[i].bytesperline; ++ f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->src_fmt.plane_fmt[i].sizeimage; ++ } ++ ++ f->fmt.pix_mp.colorspace = inst->colorspace; ++ f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc; ++ f->fmt.pix_mp.quantization = inst->quantization; ++ f->fmt.pix_mp.xfer_func = inst->xfer_func; ++ ++ return 0; ++} ++ ++const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt, ++ const struct vpu_format fmt_list[MAX_FMTS]) ++{ ++ unsigned int index; ++ ++ for (index = 0; index < MAX_FMTS; index++) { ++ if (fmt_list[index].v4l2_pix_fmt == v4l2_pix_fmt) ++ return &fmt_list[index]; ++ } ++ ++ return NULL; ++} ++ ++const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx, ++ const struct vpu_format fmt_list[MAX_FMTS]) ++{ ++ if (idx >= MAX_FMTS) ++ return NULL; ++ ++ if (!fmt_list[idx].v4l2_pix_fmt) ++ return NULL; ++ ++ return &fmt_list[idx]; ++} ++ ++enum wave_std wave5_to_vpu_std(unsigned int v4l2_pix_fmt, enum vpu_instance_type type) ++{ ++ switch (v4l2_pix_fmt) { ++ case V4L2_PIX_FMT_H264: ++ return type == VPU_INST_TYPE_DEC ? W_AVC_DEC : W_AVC_ENC; ++ case V4L2_PIX_FMT_HEVC: ++ return type == VPU_INST_TYPE_DEC ? W_HEVC_DEC : W_HEVC_ENC; ++ default: ++ return STD_UNKNOWN; ++ } ++} ++ ++void wave5_return_bufs(struct vb2_queue *q, u32 state) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct v4l2_ctrl_handler v4l2_ctrl_hdl = inst->v4l2_ctrl_hdl; ++ struct vb2_v4l2_buffer *vbuf; ++ ++ for (;;) { ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ++ vbuf = v4l2_m2m_src_buf_remove(m2m_ctx); ++ else ++ vbuf = v4l2_m2m_dst_buf_remove(m2m_ctx); ++ if (!vbuf) ++ return; ++ v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, &v4l2_ctrl_hdl); ++ v4l2_m2m_buf_done(vbuf, state); ++ } ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-helper.h b/drivers/media/platform/chips-media/wave5/wave5-helper.h +--- a/drivers/media/platform/chips-media/wave5/wave5-helper.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-helper.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,31 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ ++/* ++ * Wave5 series multi-standard codec IP - basic types ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#ifndef __WAVE_HELPER_H__ ++#define __WAVE_HELPER_H__ ++ ++#include "wave5-vpu.h" ++ ++#define FMT_TYPES 2 ++#define MAX_FMTS 12 ++ ++const char *state_to_str(enum vpu_instance_state state); ++void wave5_cleanup_instance(struct vpu_instance *inst); ++int wave5_vpu_release_device(struct file *filp, ++ int (*close_func)(struct vpu_instance *inst, u32 *fail_res), ++ char *name); ++int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq, ++ const struct vb2_ops *ops); ++int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub); ++int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f); ++const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt, ++ const struct vpu_format fmt_list[MAX_FMTS]); ++const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx, ++ const struct vpu_format fmt_list[MAX_FMTS]); ++enum wave_std wave5_to_vpu_std(unsigned int v4l2_pix_fmt, enum vpu_instance_type type); ++void wave5_return_bufs(struct vb2_queue *q, u32 state); ++#endif +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-hw.c b/drivers/media/platform/chips-media/wave5/wave5-hw.c +--- a/drivers/media/platform/chips-media/wave5/wave5-hw.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-hw.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,2554 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) ++/* ++ * Wave5 series multi-standard codec IP - wave5 backend logic ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#include ++#include ++#include "wave5-vpu.h" ++#include "wave5.h" ++#include "wave5-regdefine.h" ++ ++#define FIO_TIMEOUT 10000000 ++#define FIO_CTRL_READY BIT(31) ++#define FIO_CTRL_WRITE BIT(16) ++#define VPU_BUSY_CHECK_TIMEOUT 10000000 ++#define QUEUE_REPORT_MASK 0xffff ++ ++/* Encoder support fields */ ++#define FEATURE_HEVC10BIT_ENC BIT(3) ++#define FEATURE_AVC10BIT_ENC BIT(11) ++#define FEATURE_AVC_ENCODER BIT(1) ++#define FEATURE_HEVC_ENCODER BIT(0) ++ ++/* Decoder support fields */ ++#define FEATURE_AVC_DECODER BIT(3) ++#define FEATURE_HEVC_DECODER BIT(2) ++ ++#define FEATURE_BACKBONE BIT(16) ++#define FEATURE_VCORE_BACKBONE BIT(22) ++#define FEATURE_VCPU_BACKBONE BIT(28) ++ ++#define REMAP_CTRL_MAX_SIZE_BITS ((W5_REMAP_MAX_SIZE >> 12) & 0x1ff) ++#define REMAP_CTRL_REGISTER_VALUE(index) ( \ ++ (BIT(31) | (index << 12) | BIT(11) | REMAP_CTRL_MAX_SIZE_BITS) \ ++) ++ ++#define FASTIO_ADDRESS_MASK GENMASK(15, 0) ++#define SEQ_PARAM_PROFILE_MASK GENMASK(30, 24) ++ ++static void _wave5_print_reg_err(struct vpu_device *vpu_dev, u32 reg_fail_reason, ++ const char *func); ++#define PRINT_REG_ERR(dev, reason) _wave5_print_reg_err((dev), (reason), __func__) ++ ++static inline const char *cmd_to_str(int cmd, bool is_dec) ++{ ++ switch (cmd) { ++ case W5_INIT_VPU: ++ return "W5_INIT_VPU"; ++ case W5_WAKEUP_VPU: ++ return "W5_WAKEUP_VPU"; ++ case W5_SLEEP_VPU: ++ return "W5_SLEEP_VPU"; ++ case W5_CREATE_INSTANCE: ++ return "W5_CREATE_INSTANCE"; ++ case W5_FLUSH_INSTANCE: ++ return "W5_FLUSH_INSTANCE"; ++ case W5_DESTROY_INSTANCE: ++ return "W5_DESTROY_INSTANCE"; ++ case W5_INIT_SEQ: ++ return "W5_INIT_SEQ"; ++ case W5_SET_FB: ++ return "W5_SET_FB"; ++ case W5_DEC_ENC_PIC: ++ if (is_dec) ++ return "W5_DEC_PIC"; ++ return "W5_ENC_PIC"; ++ case W5_ENC_SET_PARAM: ++ return "W5_ENC_SET_PARAM"; ++ case W5_QUERY: ++ return "W5_QUERY"; ++ case W5_UPDATE_BS: ++ return "W5_UPDATE_BS"; ++ case W5_MAX_VPU_COMD: ++ return "W5_MAX_VPU_COMD"; ++ default: ++ return "UNKNOWN"; ++ } ++} ++ ++static void _wave5_print_reg_err(struct vpu_device *vpu_dev, u32 reg_fail_reason, ++ const char *func) ++{ ++ struct device *dev = vpu_dev->dev; ++ u32 reg_val; ++ ++ switch (reg_fail_reason) { ++ case WAVE5_SYSERR_QUEUEING_FAIL: ++ reg_val = vpu_read_reg(vpu_dev, W5_RET_QUEUE_FAIL_REASON); ++ dev_dbg(dev, "%s: queueing failure: 0x%x\n", func, reg_val); ++ break; ++ case WAVE5_SYSERR_RESULT_NOT_READY: ++ dev_err(dev, "%s: result not ready: 0x%x\n", func, reg_fail_reason); ++ break; ++ case WAVE5_SYSERR_ACCESS_VIOLATION_HW: ++ dev_err(dev, "%s: access violation: 0x%x\n", func, reg_fail_reason); ++ break; ++ case WAVE5_SYSERR_WATCHDOG_TIMEOUT: ++ dev_err(dev, "%s: watchdog timeout: 0x%x\n", func, reg_fail_reason); ++ break; ++ case WAVE5_SYSERR_BUS_ERROR: ++ dev_err(dev, "%s: bus error: 0x%x\n", func, reg_fail_reason); ++ break; ++ case WAVE5_SYSERR_DOUBLE_FAULT: ++ dev_err(dev, "%s: double fault: 0x%x\n", func, reg_fail_reason); ++ break; ++ case WAVE5_SYSERR_VPU_STILL_RUNNING: ++ dev_err(dev, "%s: still running: 0x%x\n", func, reg_fail_reason); ++ break; ++ case WAVE5_SYSERR_VLC_BUF_FULL: ++ dev_err(dev, "%s: vlc buf full: 0x%x\n", func, reg_fail_reason); ++ break; ++ default: ++ dev_err(dev, "%s: failure:: 0x%x\n", func, reg_fail_reason); ++ break; ++ } ++} ++ ++static int wave5_wait_fio_readl(struct vpu_device *vpu_dev, u32 addr, u32 val) ++{ ++ u32 ctrl; ++ int ret; ++ ++ ctrl = addr & 0xffff; ++ wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_CTRL_ADDR, ctrl); ++ ret = read_poll_timeout(wave5_vdi_read_register, ctrl, ctrl & FIO_CTRL_READY, ++ 0, FIO_TIMEOUT, false, vpu_dev, W5_VPU_FIO_CTRL_ADDR); ++ if (ret) ++ return ret; ++ ++ if (wave5_vdi_read_register(vpu_dev, W5_VPU_FIO_DATA) != val) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++static void wave5_fio_writel(struct vpu_device *vpu_dev, unsigned int addr, unsigned int data) ++{ ++ int ret; ++ unsigned int ctrl; ++ ++ wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_DATA, data); ++ ctrl = FIELD_GET(FASTIO_ADDRESS_MASK, addr); ++ ctrl |= FIO_CTRL_WRITE; ++ wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_CTRL_ADDR, ctrl); ++ ret = read_poll_timeout(wave5_vdi_read_register, ctrl, ctrl & FIO_CTRL_READY, 0, ++ FIO_TIMEOUT, false, vpu_dev, W5_VPU_FIO_CTRL_ADDR); ++ if (ret) ++ dev_dbg_ratelimited(vpu_dev->dev, "FIO write timeout: addr=0x%x data=%x\n", ++ ctrl, data); ++} ++ ++static int wave5_wait_bus_busy(struct vpu_device *vpu_dev, unsigned int addr) ++{ ++ u32 gdi_status_check_value = 0x3f; ++ ++ if (vpu_dev->product_code == WAVE521C_CODE || ++ vpu_dev->product_code == WAVE521_CODE || ++ vpu_dev->product_code == WAVE521E1_CODE) ++ gdi_status_check_value = 0x00ff1f3f; ++ ++ return wave5_wait_fio_readl(vpu_dev, addr, gdi_status_check_value); ++} ++ ++static int wave5_wait_vpu_busy(struct vpu_device *vpu_dev, unsigned int addr) ++{ ++ u32 data; ++ ++ return read_poll_timeout(wave5_vdi_read_register, data, data == 0, ++ 0, VPU_BUSY_CHECK_TIMEOUT, false, vpu_dev, addr); ++} ++ ++static int wave5_wait_vcpu_bus_busy(struct vpu_device *vpu_dev, unsigned int addr) ++{ ++ return wave5_wait_fio_readl(vpu_dev, addr, 0); ++} ++ ++bool wave5_vpu_is_init(struct vpu_device *vpu_dev) ++{ ++ return vpu_read_reg(vpu_dev, W5_VCPU_CUR_PC) != 0; ++} ++ ++unsigned int wave5_vpu_get_product_id(struct vpu_device *vpu_dev) ++{ ++ u32 val = vpu_read_reg(vpu_dev, W5_PRODUCT_NUMBER); ++ ++ switch (val) { ++ case WAVE521C_CODE: ++ return PRODUCT_ID_521; ++ case WAVE521_CODE: ++ case WAVE521C_DUAL_CODE: ++ case WAVE521E1_CODE: ++ case WAVE511_CODE: ++ case WAVE517_CODE: ++ case WAVE537_CODE: ++ dev_err(vpu_dev->dev, "Unsupported product id (%x)\n", val); ++ break; ++ default: ++ dev_err(vpu_dev->dev, "Invalid product id (%x)\n", val); ++ break; ++ } ++ ++ return PRODUCT_ID_NONE; ++} ++ ++static void wave5_bit_issue_command(struct vpu_device *vpu_dev, struct vpu_instance *inst, u32 cmd) ++{ ++ u32 instance_index; ++ u32 codec_mode; ++ ++ if (inst) { ++ instance_index = inst->id; ++ codec_mode = inst->std; ++ ++ vpu_write_reg(vpu_dev, W5_CMD_INSTANCE_INFO, (codec_mode << 16) | ++ (instance_index & 0xffff)); ++ vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1); ++ } ++ ++ vpu_write_reg(vpu_dev, W5_COMMAND, cmd); ++ ++ if (inst) { ++ dev_dbg(vpu_dev->dev, "%s: cmd=0x%x (%s)\n", __func__, cmd, ++ cmd_to_str(cmd, inst->type == VPU_INST_TYPE_DEC)); ++ } else { ++ dev_dbg(vpu_dev->dev, "%s: cmd=0x%x\n", __func__, cmd); ++ } ++ ++ vpu_write_reg(vpu_dev, W5_VPU_HOST_INT_REQ, 1); ++} ++ ++static int wave5_vpu_firmware_command_queue_error_check(struct vpu_device *dev, u32 *fail_res) ++{ ++ u32 reason = 0; ++ ++ /* Check if we were able to add a command into the VCPU QUEUE */ ++ if (!vpu_read_reg(dev, W5_RET_SUCCESS)) { ++ reason = vpu_read_reg(dev, W5_RET_FAIL_REASON); ++ PRINT_REG_ERR(dev, reason); ++ ++ /* ++ * The fail_res argument will be either NULL or 0. ++ * If the fail_res argument is NULL, then just return -EIO. ++ * Otherwise, assign the reason to fail_res, so that the ++ * calling function can use it. ++ */ ++ if (fail_res) ++ *fail_res = reason; ++ else ++ return -EIO; ++ ++ if (reason == WAVE5_SYSERR_VPU_STILL_RUNNING) ++ return -EBUSY; ++ } ++ return 0; ++} ++ ++static int send_firmware_command(struct vpu_instance *inst, u32 cmd, bool check_success, ++ u32 *queue_status, u32 *fail_result) ++{ ++ int ret; ++ ++ wave5_bit_issue_command(inst->dev, inst, cmd); ++ ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS); ++ if (ret) { ++ dev_warn(inst->dev->dev, "%s: command: '%s', timed out\n", __func__, ++ cmd_to_str(cmd, inst->type == VPU_INST_TYPE_DEC)); ++ return -ETIMEDOUT; ++ } ++ ++ if (queue_status) ++ *queue_status = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS); ++ ++ /* In some cases we want to send multiple commands before checking ++ * whether they are queued properly ++ */ ++ if (!check_success) ++ return 0; ++ ++ return wave5_vpu_firmware_command_queue_error_check(inst->dev, fail_result); ++} ++ ++static int wave5_send_query(struct vpu_device *vpu_dev, struct vpu_instance *inst, ++ enum query_opt query_opt) ++{ ++ int ret; ++ ++ vpu_write_reg(vpu_dev, W5_QUERY_OPTION, query_opt); ++ vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1); ++ wave5_bit_issue_command(vpu_dev, inst, W5_QUERY); ++ ++ ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS); ++ if (ret) { ++ dev_warn(vpu_dev->dev, "command: 'W5_QUERY', timed out opt=0x%x\n", query_opt); ++ return ret; ++ } ++ ++ return wave5_vpu_firmware_command_queue_error_check(vpu_dev, NULL); ++} ++ ++static int setup_wave5_properties(struct device *dev) ++{ ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ struct vpu_attr *p_attr = &vpu_dev->attr; ++ u32 reg_val; ++ u8 *str; ++ int ret; ++ u32 hw_config_def0, hw_config_def1, hw_config_feature; ++ ++ ret = wave5_send_query(vpu_dev, NULL, GET_VPU_INFO); ++ if (ret) ++ return ret; ++ ++ reg_val = vpu_read_reg(vpu_dev, W5_RET_PRODUCT_NAME); ++ str = (u8 *)®_val; ++ p_attr->product_name[0] = str[3]; ++ p_attr->product_name[1] = str[2]; ++ p_attr->product_name[2] = str[1]; ++ p_attr->product_name[3] = str[0]; ++ p_attr->product_name[4] = 0; ++ ++ p_attr->product_id = wave5_vpu_get_product_id(vpu_dev); ++ p_attr->product_version = vpu_read_reg(vpu_dev, W5_RET_PRODUCT_VERSION); ++ p_attr->fw_version = vpu_read_reg(vpu_dev, W5_RET_FW_VERSION); ++ p_attr->customer_id = vpu_read_reg(vpu_dev, W5_RET_CUSTOMER_ID); ++ hw_config_def0 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF0); ++ hw_config_def1 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF1); ++ hw_config_feature = vpu_read_reg(vpu_dev, W5_RET_CONF_FEATURE); ++ ++ p_attr->support_hevc10bit_enc = FIELD_GET(FEATURE_HEVC10BIT_ENC, hw_config_feature); ++ p_attr->support_avc10bit_enc = FIELD_GET(FEATURE_AVC10BIT_ENC, hw_config_feature); ++ ++ p_attr->support_decoders = FIELD_GET(FEATURE_AVC_DECODER, hw_config_def1) << STD_AVC; ++ p_attr->support_decoders |= FIELD_GET(FEATURE_HEVC_DECODER, hw_config_def1) << STD_HEVC; ++ p_attr->support_encoders = FIELD_GET(FEATURE_AVC_ENCODER, hw_config_def1) << STD_AVC; ++ p_attr->support_encoders |= FIELD_GET(FEATURE_HEVC_ENCODER, hw_config_def1) << STD_HEVC; ++ ++ p_attr->support_backbone = FIELD_GET(FEATURE_BACKBONE, hw_config_def0); ++ p_attr->support_vcpu_backbone = FIELD_GET(FEATURE_VCPU_BACKBONE, hw_config_def0); ++ p_attr->support_vcore_backbone = FIELD_GET(FEATURE_VCORE_BACKBONE, hw_config_def0); ++ ++ return 0; ++} ++ ++int wave5_vpu_get_version(struct vpu_device *vpu_dev, u32 *revision) ++{ ++ u32 reg_val; ++ int ret; ++ ++ ret = wave5_send_query(vpu_dev, NULL, GET_VPU_INFO); ++ if (ret) ++ return ret; ++ ++ reg_val = vpu_read_reg(vpu_dev, W5_RET_FW_VERSION); ++ if (revision) { ++ *revision = reg_val; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static void remap_page(struct vpu_device *vpu_dev, dma_addr_t code_base, u32 index) ++{ ++ vpu_write_reg(vpu_dev, W5_VPU_REMAP_CTRL, REMAP_CTRL_REGISTER_VALUE(index)); ++ vpu_write_reg(vpu_dev, W5_VPU_REMAP_VADDR, index * W5_REMAP_MAX_SIZE); ++ vpu_write_reg(vpu_dev, W5_VPU_REMAP_PADDR, code_base + index * W5_REMAP_MAX_SIZE); ++} ++ ++int wave5_vpu_init(struct device *dev, u8 *fw, size_t size) ++{ ++ struct vpu_buf *common_vb; ++ dma_addr_t code_base, temp_base; ++ u32 code_size, temp_size; ++ u32 i, reg_val, reason_code; ++ int ret; ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ ++ common_vb = &vpu_dev->common_mem; ++ ++ code_base = common_vb->daddr; ++ /* ALIGN TO 4KB */ ++ code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff); ++ if (code_size < size * 2) ++ return -EINVAL; ++ ++ temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET; ++ temp_size = WAVE5_TEMPBUF_SIZE; ++ ++ ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size); ++ if (ret < 0) { ++ dev_err(vpu_dev->dev, "VPU init, Writing firmware to common buffer, fail: %d\n", ++ ret); ++ return ret; ++ } ++ ++ vpu_write_reg(vpu_dev, W5_PO_CONF, 0); ++ ++ /* clear registers */ ++ ++ for (i = W5_CMD_REG_BASE; i < W5_CMD_REG_END; i += 4) ++ vpu_write_reg(vpu_dev, i, 0x00); ++ ++ remap_page(vpu_dev, code_base, W5_REMAP_INDEX0); ++ remap_page(vpu_dev, code_base, W5_REMAP_INDEX1); ++ ++ vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base); ++ vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size); ++ vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0); ++ vpu_write_reg(vpu_dev, W5_ADDR_TEMP_BASE, temp_base); ++ vpu_write_reg(vpu_dev, W5_TEMP_SIZE, temp_size); ++ ++ /* These register must be reset explicitly */ ++ vpu_write_reg(vpu_dev, W5_HW_OPTION, 0); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0); ++ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0); ++ ++ /* Encoder interrupt */ ++ reg_val = BIT(INT_WAVE5_ENC_SET_PARAM); ++ reg_val |= BIT(INT_WAVE5_ENC_PIC); ++ reg_val |= BIT(INT_WAVE5_BSBUF_FULL); ++ /* Decoder interrupt */ ++ reg_val |= BIT(INT_WAVE5_INIT_SEQ); ++ reg_val |= BIT(INT_WAVE5_DEC_PIC); ++ reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY); ++ vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val); ++ ++ reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0); ++ if (FIELD_GET(FEATURE_BACKBONE, reg_val)) { ++ reg_val = ((WAVE5_PROC_AXI_ID << 28) | ++ (WAVE5_PRP_AXI_ID << 24) | ++ (WAVE5_FBD_Y_AXI_ID << 20) | ++ (WAVE5_FBC_Y_AXI_ID << 16) | ++ (WAVE5_FBD_C_AXI_ID << 12) | ++ (WAVE5_FBC_C_AXI_ID << 8) | ++ (WAVE5_PRI_AXI_ID << 4) | ++ WAVE5_SEC_AXI_ID); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val); ++ } ++ ++ vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1); ++ vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU); ++ vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1); ++ ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS); ++ if (ret) { ++ dev_err(vpu_dev->dev, "VPU init(W5_VPU_REMAP_CORE_START) timeout\n"); ++ return ret; ++ } ++ ++ ret = wave5_vpu_firmware_command_queue_error_check(vpu_dev, &reason_code); ++ if (ret) ++ return ret; ++ ++ return setup_wave5_properties(dev); ++} ++ ++int wave5_vpu_build_up_dec_param(struct vpu_instance *inst, ++ struct dec_open_param *param) ++{ ++ int ret; ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ p_dec_info->cycle_per_tick = 256; ++ if (vpu_dev->sram_buf.size) { ++ p_dec_info->sec_axi_info.use_bit_enable = 1; ++ p_dec_info->sec_axi_info.use_ip_enable = 1; ++ p_dec_info->sec_axi_info.use_lf_row_enable = 1; ++ } ++ switch (inst->std) { ++ case W_HEVC_DEC: ++ p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_HEVC; ++ break; ++ case W_AVC_DEC: ++ p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_AVC; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ p_dec_info->vb_work.size = WAVE521DEC_WORKBUF_SIZE; ++ ret = wave5_vdi_allocate_dma_memory(inst->dev, &p_dec_info->vb_work); ++ if (ret) ++ return ret; ++ ++ vpu_write_reg(inst->dev, W5_CMD_DEC_VCORE_INFO, 1); ++ ++ wave5_vdi_clear_memory(inst->dev, &p_dec_info->vb_work); ++ ++ vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_dec_info->vb_work.daddr); ++ vpu_write_reg(inst->dev, W5_WORK_SIZE, p_dec_info->vb_work.size); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr); ++ vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size); ++ ++ vpu_write_reg(inst->dev, W5_CMD_DEC_BS_START_ADDR, p_dec_info->stream_buf_start_addr); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_BS_SIZE, p_dec_info->stream_buf_size); ++ ++ /* NOTE: SDMA reads MSB first */ ++ vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, BITSTREAM_ENDIANNESS_BIG_ENDIAN); ++ /* This register must be reset explicitly */ ++ vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0); ++ vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, (COMMAND_QUEUE_DEPTH - 1)); ++ ++ ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL); ++ if (ret) { ++ wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_work); ++ return ret; ++ } ++ ++ p_dec_info->product_code = vpu_read_reg(inst->dev, W5_PRODUCT_NUMBER); ++ ++ return 0; ++} ++ ++int wave5_vpu_hw_flush_instance(struct vpu_instance *inst) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ u32 instance_queue_count, report_queue_count; ++ u32 reg_val = 0; ++ u32 fail_res = 0; ++ int ret; ++ ++ ret = send_firmware_command(inst, W5_FLUSH_INSTANCE, true, ®_val, &fail_res); ++ if (ret) ++ return ret; ++ ++ instance_queue_count = (reg_val >> 16) & 0xff; ++ report_queue_count = (reg_val & QUEUE_REPORT_MASK); ++ if (instance_queue_count != 0 || report_queue_count != 0) { ++ dev_warn(inst->dev->dev, ++ "FLUSH_INSTANCE cmd didn't reset the amount of queued commands & reports"); ++ } ++ ++ /* reset our local copy of the counts */ ++ p_dec_info->instance_queue_count = 0; ++ p_dec_info->report_queue_count = 0; ++ ++ return 0; ++} ++ ++static u32 get_bitstream_options(struct dec_info *info) ++{ ++ u32 bs_option = BSOPTION_ENABLE_EXPLICIT_END; ++ ++ if (info->stream_endflag) ++ bs_option |= BSOPTION_HIGHLIGHT_STREAM_END; ++ return bs_option; ++} ++ ++int wave5_vpu_dec_init_seq(struct vpu_instance *inst) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ u32 cmd_option = INIT_SEQ_NORMAL; ++ u32 reg_val, fail_res; ++ int ret; ++ ++ if (!inst->codec_info) ++ return -EINVAL; ++ ++ vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr); ++ vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr); ++ ++ vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info)); ++ ++ vpu_write_reg(inst->dev, W5_COMMAND_OPTION, cmd_option); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info->user_data_enable); ++ ++ ret = send_firmware_command(inst, W5_INIT_SEQ, true, ®_val, &fail_res); ++ if (ret) ++ return ret; ++ ++ p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff; ++ p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK); ++ ++ dev_dbg(inst->dev->dev, "%s: init seq sent (queue %u : %u)\n", __func__, ++ p_dec_info->instance_queue_count, p_dec_info->report_queue_count); ++ ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static void wave5_get_dec_seq_result(struct vpu_instance *inst, struct dec_initial_info *info) ++{ ++ u32 reg_val; ++ u32 profile_compatibility_flag; ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ ++ p_dec_info->stream_rd_ptr = wave5_dec_get_rd_ptr(inst); ++ info->rd_ptr = p_dec_info->stream_rd_ptr; ++ ++ p_dec_info->frame_display_flag = vpu_read_reg(inst->dev, W5_RET_DEC_DISP_IDC); ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_SIZE); ++ info->pic_width = ((reg_val >> 16) & 0xffff); ++ info->pic_height = (reg_val & 0xffff); ++ info->min_frame_buffer_count = vpu_read_reg(inst->dev, W5_RET_DEC_NUM_REQUIRED_FB); ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_CROP_LEFT_RIGHT); ++ info->pic_crop_rect.left = (reg_val >> 16) & 0xffff; ++ info->pic_crop_rect.right = reg_val & 0xffff; ++ reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_CROP_TOP_BOTTOM); ++ info->pic_crop_rect.top = (reg_val >> 16) & 0xffff; ++ info->pic_crop_rect.bottom = reg_val & 0xffff; ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_COLOR_SAMPLE_INFO); ++ info->luma_bitdepth = reg_val & 0xf; ++ info->chroma_bitdepth = (reg_val >> 4) & 0xf; ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_SEQ_PARAM); ++ profile_compatibility_flag = (reg_val >> 12) & 0xff; ++ info->profile = (reg_val >> 24) & 0x1f; ++ ++ if (inst->std == W_HEVC_DEC) { ++ /* guessing profile */ ++ if (!info->profile) { ++ if ((profile_compatibility_flag & 0x06) == 0x06) ++ info->profile = HEVC_PROFILE_MAIN; /* main profile */ ++ else if (profile_compatibility_flag & 0x04) ++ info->profile = HEVC_PROFILE_MAIN10; /* main10 profile */ ++ else if (profile_compatibility_flag & 0x08) ++ /* main still picture profile */ ++ info->profile = HEVC_PROFILE_STILLPICTURE; ++ else ++ info->profile = HEVC_PROFILE_MAIN; /* for old version HM */ ++ } ++ } else if (inst->std == W_AVC_DEC) { ++ info->profile = FIELD_GET(SEQ_PARAM_PROFILE_MASK, reg_val); ++ } ++ ++ info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE); ++ info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE); ++ p_dec_info->vlc_buf_size = info->vlc_buf_size; ++ p_dec_info->param_buf_size = info->param_buf_size; ++} ++ ++int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct dec_initial_info *info) ++{ ++ int ret; ++ u32 reg_val; ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ ++ vpu_write_reg(inst->dev, W5_CMD_DEC_ADDR_REPORT_BASE, p_dec_info->user_data_buf_addr); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_SIZE, p_dec_info->user_data_buf_size); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_PARAM, REPORT_PARAM_ENDIANNESS_BIG_ENDIAN); ++ ++ /* send QUERY cmd */ ++ ret = wave5_send_query(inst->dev, inst, GET_RESULT); ++ if (ret) ++ return ret; ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS); ++ ++ p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff; ++ p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK); ++ ++ dev_dbg(inst->dev->dev, "%s: init seq complete (queue %u : %u)\n", __func__, ++ p_dec_info->instance_queue_count, p_dec_info->report_queue_count); ++ ++ /* this is not a fatal error, set ret to -EIO but don't return immediately */ ++ if (vpu_read_reg(inst->dev, W5_RET_DEC_DECODING_SUCCESS) != 1) { ++ info->seq_init_err_reason = vpu_read_reg(inst->dev, W5_RET_DEC_ERR_INFO); ++ ret = -EIO; ++ } ++ ++ wave5_get_dec_seq_result(inst, info); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_buffer *fb_arr, ++ enum tiled_map_type map_type, unsigned int count) ++{ ++ int ret; ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ struct dec_initial_info *init_info = &p_dec_info->initial_info; ++ size_t remain, idx, j, i, cnt_8_chunk, size; ++ u32 start_no, end_no; ++ u32 reg_val, cbcr_interleave, nv21, pic_size; ++ u32 addr_y, addr_cb, addr_cr; ++ u32 mv_col_size, frame_width, frame_height, fbc_y_tbl_size, fbc_c_tbl_size; ++ struct vpu_buf vb_buf; ++ bool justified = WTL_RIGHT_JUSTIFIED; ++ u32 format_no = WTL_PIXEL_8BIT; ++ u32 color_format = 0; ++ u32 pixel_order = 1; ++ u32 bwb_flag = (map_type == LINEAR_FRAME_MAP) ? 1 : 0; ++ ++ cbcr_interleave = inst->cbcr_interleave; ++ nv21 = inst->nv21; ++ mv_col_size = 0; ++ fbc_y_tbl_size = 0; ++ fbc_c_tbl_size = 0; ++ ++ if (map_type >= COMPRESSED_FRAME_MAP) { ++ cbcr_interleave = 0; ++ nv21 = 0; ++ ++ switch (inst->std) { ++ case W_HEVC_DEC: ++ mv_col_size = WAVE5_DEC_HEVC_BUF_SIZE(init_info->pic_width, ++ init_info->pic_height); ++ break; ++ case W_AVC_DEC: ++ mv_col_size = WAVE5_DEC_AVC_BUF_SIZE(init_info->pic_width, ++ init_info->pic_height); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (inst->std == W_HEVC_DEC || inst->std == W_AVC_DEC) { ++ size = ALIGN(ALIGN(mv_col_size, 16), BUFFER_MARGIN) + BUFFER_MARGIN; ++ ret = wave5_vdi_allocate_array(inst->dev, p_dec_info->vb_mv, count, size); ++ if (ret) ++ goto free_mv_buffers; ++ } ++ ++ frame_width = init_info->pic_width; ++ frame_height = init_info->pic_height; ++ fbc_y_tbl_size = ALIGN(WAVE5_FBC_LUMA_TABLE_SIZE(frame_width, frame_height), 16); ++ fbc_c_tbl_size = ALIGN(WAVE5_FBC_CHROMA_TABLE_SIZE(frame_width, frame_height), 16); ++ ++ size = ALIGN(fbc_y_tbl_size, BUFFER_MARGIN) + BUFFER_MARGIN; ++ ret = wave5_vdi_allocate_array(inst->dev, p_dec_info->vb_fbc_y_tbl, count, size); ++ if (ret) ++ goto free_fbc_y_tbl_buffers; ++ ++ size = ALIGN(fbc_c_tbl_size, BUFFER_MARGIN) + BUFFER_MARGIN; ++ ret = wave5_vdi_allocate_array(inst->dev, p_dec_info->vb_fbc_c_tbl, count, size); ++ if (ret) ++ goto free_fbc_c_tbl_buffers; ++ ++ pic_size = (init_info->pic_width << 16) | (init_info->pic_height); ++ ++ vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) + ++ (p_dec_info->param_buf_size * COMMAND_QUEUE_DEPTH); ++ vb_buf.daddr = 0; ++ ++ if (vb_buf.size != p_dec_info->vb_task.size) { ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task); ++ ret = wave5_vdi_allocate_dma_memory(inst->dev, &vb_buf); ++ if (ret) ++ goto free_fbc_c_tbl_buffers; ++ ++ p_dec_info->vb_task = vb_buf; ++ } ++ ++ vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF, ++ p_dec_info->vb_task.daddr); ++ vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_buf.size); ++ } else { ++ pic_size = (init_info->pic_width << 16) | (init_info->pic_height); ++ ++ if (inst->output_format == FORMAT_422) ++ color_format = 1; ++ } ++ vpu_write_reg(inst->dev, W5_PIC_SIZE, pic_size); ++ ++ reg_val = (bwb_flag << 28) | ++ (pixel_order << 23) | ++ (justified << 22) | ++ (format_no << 20) | ++ (color_format << 19) | ++ (nv21 << 17) | ++ (cbcr_interleave << 16) | ++ (fb_arr[0].stride); ++ vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, reg_val); ++ ++ remain = count; ++ cnt_8_chunk = DIV_ROUND_UP(count, 8); ++ idx = 0; ++ for (j = 0; j < cnt_8_chunk; j++) { ++ reg_val = (j == cnt_8_chunk - 1) << 4 | ((j == 0) << 3); ++ vpu_write_reg(inst->dev, W5_SFB_OPTION, reg_val); ++ start_no = j * 8; ++ end_no = start_no + ((remain >= 8) ? 8 : remain) - 1; ++ ++ vpu_write_reg(inst->dev, W5_SET_FB_NUM, (start_no << 8) | end_no); ++ ++ for (i = 0; i < 8 && i < remain; i++) { ++ addr_y = fb_arr[i + start_no].buf_y; ++ addr_cb = fb_arr[i + start_no].buf_cb; ++ addr_cr = fb_arr[i + start_no].buf_cr; ++ vpu_write_reg(inst->dev, W5_ADDR_LUMA_BASE0 + (i << 4), addr_y); ++ vpu_write_reg(inst->dev, W5_ADDR_CB_BASE0 + (i << 4), addr_cb); ++ if (map_type >= COMPRESSED_FRAME_MAP) { ++ /* luma FBC offset table */ ++ vpu_write_reg(inst->dev, W5_ADDR_FBC_Y_OFFSET0 + (i << 4), ++ p_dec_info->vb_fbc_y_tbl[idx].daddr); ++ /* chroma FBC offset table */ ++ vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4), ++ p_dec_info->vb_fbc_c_tbl[idx].daddr); ++ vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2), ++ p_dec_info->vb_mv[idx].daddr); ++ } else { ++ vpu_write_reg(inst->dev, W5_ADDR_CR_BASE0 + (i << 4), addr_cr); ++ vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4), 0); ++ vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2), 0); ++ } ++ idx++; ++ } ++ remain -= i; ++ ++ ret = send_firmware_command(inst, W5_SET_FB, false, NULL, NULL); ++ if (ret) ++ goto free_buffers; ++ } ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_SUCCESS); ++ if (!reg_val) { ++ ret = -EIO; ++ goto free_buffers; ++ } ++ ++ return 0; ++ ++free_buffers: ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task); ++free_fbc_c_tbl_buffers: ++ for (i = 0; i < count; i++) ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_c_tbl[i]); ++free_fbc_y_tbl_buffers: ++ for (i = 0; i < count; i++) ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_y_tbl[i]); ++free_mv_buffers: ++ for (i = 0; i < count; i++) ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_mv[i]); ++ return ret; ++} ++ ++int wave5_vpu_decode(struct vpu_instance *inst, u32 *fail_res) ++{ ++ u32 reg_val; ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret; ++ ++ vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr); ++ vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr); ++ ++ vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info)); ++ ++ /* secondary AXI */ ++ reg_val = p_dec_info->sec_axi_info.use_bit_enable | ++ (p_dec_info->sec_axi_info.use_ip_enable << 9) | ++ (p_dec_info->sec_axi_info.use_lf_row_enable << 15); ++ vpu_write_reg(inst->dev, W5_USE_SEC_AXI, reg_val); ++ ++ /* set attributes of user buffer */ ++ vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info->user_data_enable); ++ ++ vpu_write_reg(inst->dev, W5_COMMAND_OPTION, DEC_PIC_NORMAL); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_TEMPORAL_ID_PLUS1, ++ (p_dec_info->target_spatial_id << 9) | ++ (p_dec_info->temp_id_select_mode << 8) | p_dec_info->target_temp_id); ++ vpu_write_reg(inst->dev, W5_CMD_SEQ_CHANGE_ENABLE_FLAG, p_dec_info->seq_change_mask); ++ /* When reordering is disabled we force the latency of the framebuffers */ ++ vpu_write_reg(inst->dev, W5_CMD_DEC_FORCE_FB_LATENCY_PLUS1, !p_dec_info->reorder_enable); ++ ++ ret = send_firmware_command(inst, W5_DEC_ENC_PIC, true, ®_val, fail_res); ++ if (ret == -ETIMEDOUT) ++ return ret; ++ ++ p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff; ++ p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK); ++ ++ dev_dbg(inst->dev->dev, "%s: dec pic sent (queue %u : %u)\n", __func__, ++ p_dec_info->instance_queue_count, p_dec_info->report_queue_count); ++ ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++int wave5_vpu_dec_get_result(struct vpu_instance *inst, struct dec_output_info *result) ++{ ++ int ret; ++ u32 index, nal_unit_type, reg_val, sub_layer_info; ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ vpu_write_reg(inst->dev, W5_CMD_DEC_ADDR_REPORT_BASE, p_dec_info->user_data_buf_addr); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_SIZE, p_dec_info->user_data_buf_size); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_PARAM, REPORT_PARAM_ENDIANNESS_BIG_ENDIAN); ++ ++ /* send QUERY cmd */ ++ ret = wave5_send_query(vpu_dev, inst, GET_RESULT); ++ if (ret) ++ return ret; ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS); ++ ++ p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff; ++ p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK); ++ ++ dev_dbg(inst->dev->dev, "%s: dec pic complete (queue %u : %u)\n", __func__, ++ p_dec_info->instance_queue_count, p_dec_info->report_queue_count); ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_TYPE); ++ ++ nal_unit_type = (reg_val >> 4) & 0x3f; ++ ++ if (inst->std == W_HEVC_DEC) { ++ if (reg_val & 0x04) ++ result->pic_type = PIC_TYPE_B; ++ else if (reg_val & 0x02) ++ result->pic_type = PIC_TYPE_P; ++ else if (reg_val & 0x01) ++ result->pic_type = PIC_TYPE_I; ++ else ++ result->pic_type = PIC_TYPE_MAX; ++ if ((nal_unit_type == 19 || nal_unit_type == 20) && result->pic_type == PIC_TYPE_I) ++ /* IDR_W_RADL, IDR_N_LP */ ++ result->pic_type = PIC_TYPE_IDR; ++ } else if (inst->std == W_AVC_DEC) { ++ if (reg_val & 0x04) ++ result->pic_type = PIC_TYPE_B; ++ else if (reg_val & 0x02) ++ result->pic_type = PIC_TYPE_P; ++ else if (reg_val & 0x01) ++ result->pic_type = PIC_TYPE_I; ++ else ++ result->pic_type = PIC_TYPE_MAX; ++ if (nal_unit_type == 5 && result->pic_type == PIC_TYPE_I) ++ result->pic_type = PIC_TYPE_IDR; ++ } ++ index = vpu_read_reg(inst->dev, W5_RET_DEC_DISPLAY_INDEX); ++ result->index_frame_display = index; ++ index = vpu_read_reg(inst->dev, W5_RET_DEC_DECODED_INDEX); ++ result->index_frame_decoded = index; ++ result->index_frame_decoded_for_tiled = index; ++ ++ sub_layer_info = vpu_read_reg(inst->dev, W5_RET_DEC_SUB_LAYER_INFO); ++ result->temporal_id = sub_layer_info & 0x7; ++ ++ if (inst->std == W_HEVC_DEC || inst->std == W_AVC_DEC) { ++ result->decoded_poc = -1; ++ if (result->index_frame_decoded >= 0 || ++ result->index_frame_decoded == DECODED_IDX_FLAG_SKIP) ++ result->decoded_poc = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_POC); ++ } ++ ++ result->sequence_changed = vpu_read_reg(inst->dev, W5_RET_DEC_NOTIFICATION); ++ reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_SIZE); ++ result->dec_pic_width = reg_val >> 16; ++ result->dec_pic_height = reg_val & 0xffff; ++ ++ if (result->sequence_changed) { ++ memcpy((void *)&p_dec_info->new_seq_info, (void *)&p_dec_info->initial_info, ++ sizeof(struct dec_initial_info)); ++ wave5_get_dec_seq_result(inst, &p_dec_info->new_seq_info); ++ } ++ ++ result->dec_host_cmd_tick = vpu_read_reg(inst->dev, W5_RET_DEC_HOST_CMD_TICK); ++ result->dec_decode_end_tick = vpu_read_reg(inst->dev, W5_RET_DEC_DECODING_ENC_TICK); ++ ++ if (!p_dec_info->first_cycle_check) { ++ result->frame_cycle = ++ (result->dec_decode_end_tick - result->dec_host_cmd_tick) * ++ p_dec_info->cycle_per_tick; ++ vpu_dev->last_performance_cycles = result->dec_decode_end_tick; ++ p_dec_info->first_cycle_check = true; ++ } else if (result->index_frame_decoded_for_tiled != -1) { ++ result->frame_cycle = ++ (result->dec_decode_end_tick - vpu_dev->last_performance_cycles) * ++ p_dec_info->cycle_per_tick; ++ vpu_dev->last_performance_cycles = result->dec_decode_end_tick; ++ if (vpu_dev->last_performance_cycles < result->dec_host_cmd_tick) ++ result->frame_cycle = ++ (result->dec_decode_end_tick - result->dec_host_cmd_tick) * ++ p_dec_info->cycle_per_tick; ++ } ++ ++ /* no remaining command. reset frame cycle. */ ++ if (p_dec_info->instance_queue_count == 0 && p_dec_info->report_queue_count == 0) ++ p_dec_info->first_cycle_check = false; ++ ++ return 0; ++} ++ ++int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size) ++{ ++ struct vpu_buf *common_vb; ++ dma_addr_t code_base, temp_base; ++ dma_addr_t old_code_base, temp_size; ++ u32 code_size, reason_code; ++ u32 reg_val; ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ ++ common_vb = &vpu_dev->common_mem; ++ ++ code_base = common_vb->daddr; ++ /* ALIGN TO 4KB */ ++ code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff); ++ if (code_size < size * 2) ++ return -EINVAL; ++ temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET; ++ temp_size = WAVE5_TEMPBUF_SIZE; ++ ++ old_code_base = vpu_read_reg(vpu_dev, W5_VPU_REMAP_PADDR); ++ ++ if (old_code_base != code_base + W5_REMAP_INDEX1 * W5_REMAP_MAX_SIZE) { ++ int ret; ++ ++ ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size); ++ if (ret < 0) { ++ dev_err(vpu_dev->dev, ++ "VPU init, Writing firmware to common buffer, fail: %d\n", ret); ++ return ret; ++ } ++ ++ vpu_write_reg(vpu_dev, W5_PO_CONF, 0); ++ ++ ret = wave5_vpu_reset(dev, SW_RESET_ON_BOOT); ++ if (ret < 0) { ++ dev_err(vpu_dev->dev, "VPU init, Resetting the VPU, fail: %d\n", ret); ++ return ret; ++ } ++ ++ remap_page(vpu_dev, code_base, W5_REMAP_INDEX0); ++ remap_page(vpu_dev, code_base, W5_REMAP_INDEX1); ++ ++ vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base); ++ vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size); ++ vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0); ++ vpu_write_reg(vpu_dev, W5_ADDR_TEMP_BASE, temp_base); ++ vpu_write_reg(vpu_dev, W5_TEMP_SIZE, temp_size); ++ ++ /* These register must be reset explicitly */ ++ vpu_write_reg(vpu_dev, W5_HW_OPTION, 0); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0); ++ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0); ++ ++ /* Encoder interrupt */ ++ reg_val = BIT(INT_WAVE5_ENC_SET_PARAM); ++ reg_val |= BIT(INT_WAVE5_ENC_PIC); ++ reg_val |= BIT(INT_WAVE5_BSBUF_FULL); ++ /* Decoder interrupt */ ++ reg_val |= BIT(INT_WAVE5_INIT_SEQ); ++ reg_val |= BIT(INT_WAVE5_DEC_PIC); ++ reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY); ++ vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val); ++ ++ reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0); ++ if (FIELD_GET(FEATURE_BACKBONE, reg_val)) { ++ reg_val = ((WAVE5_PROC_AXI_ID << 28) | ++ (WAVE5_PRP_AXI_ID << 24) | ++ (WAVE5_FBD_Y_AXI_ID << 20) | ++ (WAVE5_FBC_Y_AXI_ID << 16) | ++ (WAVE5_FBD_C_AXI_ID << 12) | ++ (WAVE5_FBC_C_AXI_ID << 8) | ++ (WAVE5_PRI_AXI_ID << 4) | ++ WAVE5_SEC_AXI_ID); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val); ++ } ++ ++ vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1); ++ vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU); ++ vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1); ++ ++ ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS); ++ if (ret) { ++ dev_err(vpu_dev->dev, "VPU reinit(W5_VPU_REMAP_CORE_START) timeout\n"); ++ return ret; ++ } ++ ++ ret = wave5_vpu_firmware_command_queue_error_check(vpu_dev, &reason_code); ++ if (ret) ++ return ret; ++ } ++ ++ return setup_wave5_properties(dev); ++} ++ ++static int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uint16_t *code, ++ size_t size) ++{ ++ u32 reg_val; ++ struct vpu_buf *common_vb; ++ dma_addr_t code_base; ++ u32 code_size, reason_code; ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ int ret; ++ ++ if (i_sleep_wake) { ++ ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS); ++ if (ret) ++ return ret; ++ ++ /* ++ * Declare who has ownership for the host interface access ++ * 1 = VPU ++ * 0 = Host processor ++ */ ++ vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1); ++ vpu_write_reg(vpu_dev, W5_COMMAND, W5_SLEEP_VPU); ++ /* Send an interrupt named HOST to the VPU */ ++ vpu_write_reg(vpu_dev, W5_VPU_HOST_INT_REQ, 1); ++ ++ ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS); ++ if (ret) ++ return ret; ++ ++ ret = wave5_vpu_firmware_command_queue_error_check(vpu_dev, &reason_code); ++ if (ret) ++ return ret; ++ } else { /* restore */ ++ common_vb = &vpu_dev->common_mem; ++ ++ code_base = common_vb->daddr; ++ /* ALIGN TO 4KB */ ++ code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff); ++ if (code_size < size * 2) { ++ dev_err(dev, "size too small\n"); ++ return -EINVAL; ++ } ++ ++ /* Power on without DEBUG mode */ ++ vpu_write_reg(vpu_dev, W5_PO_CONF, 0); ++ ++ remap_page(vpu_dev, code_base, W5_REMAP_INDEX0); ++ remap_page(vpu_dev, code_base, W5_REMAP_INDEX1); ++ ++ vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base); ++ vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size); ++ vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0); ++ ++ /* These register must be reset explicitly */ ++ vpu_write_reg(vpu_dev, W5_HW_OPTION, 0); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, 0); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, 0); ++ vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, 0); ++ ++ /* Encoder interrupt */ ++ reg_val = BIT(INT_WAVE5_ENC_SET_PARAM); ++ reg_val |= BIT(INT_WAVE5_ENC_PIC); ++ reg_val |= BIT(INT_WAVE5_BSBUF_FULL); ++ /* Decoder interrupt */ ++ reg_val |= BIT(INT_WAVE5_INIT_SEQ); ++ reg_val |= BIT(INT_WAVE5_DEC_PIC); ++ reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY); ++ vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val); ++ ++ reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0); ++ if (FIELD_GET(FEATURE_BACKBONE, reg_val)) { ++ reg_val = ((WAVE5_PROC_AXI_ID << 28) | ++ (WAVE5_PRP_AXI_ID << 24) | ++ (WAVE5_FBD_Y_AXI_ID << 20) | ++ (WAVE5_FBC_Y_AXI_ID << 16) | ++ (WAVE5_FBD_C_AXI_ID << 12) | ++ (WAVE5_FBC_C_AXI_ID << 8) | ++ (WAVE5_PRI_AXI_ID << 4) | ++ WAVE5_SEC_AXI_ID); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val); ++ } ++ ++ vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1); ++ vpu_write_reg(vpu_dev, W5_COMMAND, W5_WAKEUP_VPU); ++ /* Start VPU after settings */ ++ vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1); ++ ++ ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS); ++ if (ret) { ++ dev_err(vpu_dev->dev, "VPU wakeup(W5_VPU_REMAP_CORE_START) timeout\n"); ++ return ret; ++ } ++ ++ return wave5_vpu_firmware_command_queue_error_check(vpu_dev, &reason_code); ++ } ++ ++ return 0; ++} ++ ++int wave5_vpu_reset(struct device *dev, enum sw_reset_mode reset_mode) ++{ ++ u32 val = 0; ++ int ret = 0; ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ struct vpu_attr *p_attr = &vpu_dev->attr; ++ /* VPU doesn't send response. force to set BUSY flag to 0. */ ++ vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 0); ++ ++ if (reset_mode == SW_RESET_SAFETY) { ++ ret = wave5_vpu_sleep_wake(dev, true, NULL, 0); ++ if (ret) ++ return ret; ++ } ++ ++ val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0); ++ if ((val >> 16) & 0x1) ++ p_attr->support_backbone = true; ++ if ((val >> 22) & 0x1) ++ p_attr->support_vcore_backbone = true; ++ if ((val >> 28) & 0x1) ++ p_attr->support_vcpu_backbone = true; ++ ++ /* waiting for completion of bus transaction */ ++ if (p_attr->support_backbone) { ++ dev_dbg(dev, "%s: backbone supported\n", __func__); ++ ++ if (p_attr->support_vcore_backbone) { ++ if (p_attr->support_vcpu_backbone) { ++ /* step1 : disable request */ ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0xFF); ++ ++ /* step2 : waiting for completion of bus transaction */ ++ ret = wave5_wait_vcpu_bus_busy(vpu_dev, ++ W5_BACKBONE_BUS_STATUS_VCPU); ++ if (ret) { ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0x00); ++ return ret; ++ } ++ } ++ /* step1 : disable request */ ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x7); ++ ++ /* step2 : waiting for completion of bus transaction */ ++ if (wave5_wait_bus_busy(vpu_dev, W5_BACKBONE_BUS_STATUS_VCORE0)) { ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x00); ++ return -EBUSY; ++ } ++ } else { ++ /* step1 : disable request */ ++ wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x7); ++ ++ /* step2 : waiting for completion of bus transaction */ ++ if (wave5_wait_bus_busy(vpu_dev, W5_COMBINED_BACKBONE_BUS_STATUS)) { ++ wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x00); ++ return -EBUSY; ++ } ++ } ++ } else { ++ dev_dbg(dev, "%s: backbone NOT supported\n", __func__); ++ /* step1 : disable request */ ++ wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x100); ++ ++ /* step2 : waiting for completion of bus transaction */ ++ ret = wave5_wait_bus_busy(vpu_dev, W5_GDI_BUS_STATUS); ++ if (ret) { ++ wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x00); ++ return ret; ++ } ++ } ++ ++ switch (reset_mode) { ++ case SW_RESET_ON_BOOT: ++ case SW_RESET_FORCE: ++ case SW_RESET_SAFETY: ++ val = W5_RST_BLOCK_ALL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (val) { ++ vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, val); ++ ++ ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_RESET_STATUS); ++ if (ret) { ++ vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, 0); ++ return ret; ++ } ++ vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, 0); ++ } ++ /* step3 : must clear GDI_BUS_CTRL after done SW_RESET */ ++ if (p_attr->support_backbone) { ++ if (p_attr->support_vcore_backbone) { ++ if (p_attr->support_vcpu_backbone) ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0x00); ++ wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x00); ++ } else { ++ wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x00); ++ } ++ } else { ++ wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x00); ++ } ++ if (reset_mode == SW_RESET_SAFETY || reset_mode == SW_RESET_FORCE) ++ ret = wave5_vpu_sleep_wake(dev, false, NULL, 0); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_finish_seq(struct vpu_instance *inst, u32 *fail_res) ++{ ++ return send_firmware_command(inst, W5_DESTROY_INSTANCE, true, NULL, fail_res); ++} ++ ++int wave5_vpu_dec_set_bitstream_flag(struct vpu_instance *inst, bool eos) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ ++ p_dec_info->stream_endflag = eos ? 1 : 0; ++ vpu_write_reg(inst->dev, W5_BS_OPTION, get_bitstream_options(p_dec_info)); ++ vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr); ++ ++ return send_firmware_command(inst, W5_UPDATE_BS, true, NULL, NULL); ++} ++ ++int wave5_dec_clr_disp_flag(struct vpu_instance *inst, unsigned int index) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret; ++ ++ vpu_write_reg(inst->dev, W5_CMD_DEC_CLR_DISP_IDC, BIT(index)); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_SET_DISP_IDC, 0); ++ ++ ret = wave5_send_query(inst->dev, inst, UPDATE_DISP_FLAG); ++ if (ret) ++ return ret; ++ ++ p_dec_info->frame_display_flag = vpu_read_reg(inst->dev, W5_RET_DEC_DISP_IDC); ++ ++ return 0; ++} ++ ++int wave5_dec_set_disp_flag(struct vpu_instance *inst, unsigned int index) ++{ ++ int ret; ++ ++ vpu_write_reg(inst->dev, W5_CMD_DEC_CLR_DISP_IDC, 0); ++ vpu_write_reg(inst->dev, W5_CMD_DEC_SET_DISP_IDC, BIT(index)); ++ ++ ret = wave5_send_query(inst->dev, inst, UPDATE_DISP_FLAG); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++int wave5_vpu_clear_interrupt(struct vpu_instance *inst, u32 flags) ++{ ++ u32 interrupt_reason; ++ ++ interrupt_reason = vpu_read_reg(inst->dev, W5_VPU_VINT_REASON_USR); ++ interrupt_reason &= ~flags; ++ vpu_write_reg(inst->dev, W5_VPU_VINT_REASON_USR, interrupt_reason); ++ ++ return 0; ++} ++ ++dma_addr_t wave5_dec_get_rd_ptr(struct vpu_instance *inst) ++{ ++ int ret; ++ ++ ret = wave5_send_query(inst->dev, inst, GET_BS_RD_PTR); ++ if (ret) ++ return inst->codec_info->dec_info.stream_rd_ptr; ++ ++ return vpu_read_reg(inst->dev, W5_RET_QUERY_DEC_BS_RD_PTR); ++} ++ ++int wave5_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr) ++{ ++ int ret; ++ ++ vpu_write_reg(inst->dev, W5_RET_QUERY_DEC_SET_BS_RD_PTR, addr); ++ ++ ret = wave5_send_query(inst->dev, inst, SET_BS_RD_PTR); ++ ++ return ret; ++} ++ ++/************************************************************************/ ++/* ENCODER functions */ ++/************************************************************************/ ++ ++int wave5_vpu_build_up_enc_param(struct device *dev, struct vpu_instance *inst, ++ struct enc_open_param *open_param) ++{ ++ int ret; ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ u32 reg_val; ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ dma_addr_t buffer_addr; ++ size_t buffer_size; ++ ++ p_enc_info->cycle_per_tick = 256; ++ if (vpu_dev->sram_buf.size) { ++ p_enc_info->sec_axi_info.use_enc_rdo_enable = 1; ++ p_enc_info->sec_axi_info.use_enc_lf_enable = 1; ++ } ++ ++ p_enc_info->vb_work.size = WAVE521ENC_WORKBUF_SIZE; ++ ret = wave5_vdi_allocate_dma_memory(vpu_dev, &p_enc_info->vb_work); ++ if (ret) { ++ memset(&p_enc_info->vb_work, 0, sizeof(p_enc_info->vb_work)); ++ return ret; ++ } ++ ++ wave5_vdi_clear_memory(vpu_dev, &p_enc_info->vb_work); ++ ++ vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_enc_info->vb_work.daddr); ++ vpu_write_reg(inst->dev, W5_WORK_SIZE, p_enc_info->vb_work.size); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr); ++ vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size); ++ ++ reg_val = (open_param->line_buf_int_en << 6) | BITSTREAM_ENDIANNESS_BIG_ENDIAN; ++ vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, reg_val); ++ vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, 0); ++ vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, (COMMAND_QUEUE_DEPTH - 1)); ++ ++ /* This register must be reset explicitly */ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SRC_OPTIONS, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_VCORE_INFO, 1); ++ ++ ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL); ++ if (ret) ++ goto free_vb_work; ++ ++ buffer_addr = open_param->bitstream_buffer; ++ buffer_size = open_param->bitstream_buffer_size; ++ p_enc_info->stream_rd_ptr = buffer_addr; ++ p_enc_info->stream_wr_ptr = buffer_addr; ++ p_enc_info->line_buf_int_en = open_param->line_buf_int_en; ++ p_enc_info->stream_buf_start_addr = buffer_addr; ++ p_enc_info->stream_buf_size = buffer_size; ++ p_enc_info->stream_buf_end_addr = buffer_addr + buffer_size; ++ p_enc_info->stride = 0; ++ p_enc_info->initial_info_obtained = false; ++ p_enc_info->product_code = vpu_read_reg(inst->dev, W5_PRODUCT_NUMBER); ++ ++ return 0; ++free_vb_work: ++ if (wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_work)) ++ memset(&p_enc_info->vb_work, 0, sizeof(p_enc_info->vb_work)); ++ return ret; ++} ++ ++static void wave5_set_enc_crop_info(u32 codec, struct enc_wave_param *param, int rot_mode, ++ int src_width, int src_height) ++{ ++ int aligned_width = (codec == W_HEVC_ENC) ? ALIGN(src_width, 32) : ALIGN(src_width, 16); ++ int aligned_height = (codec == W_HEVC_ENC) ? ALIGN(src_height, 32) : ALIGN(src_height, 16); ++ int pad_right, pad_bot; ++ int crop_right, crop_left, crop_top, crop_bot; ++ int prp_mode = rot_mode >> 1; /* remove prp_enable bit */ ++ ++ if (codec == W_HEVC_ENC && ++ (!rot_mode || prp_mode == 14)) /* prp_mode 14 : hor_mir && ver_mir && rot_180 */ ++ return; ++ ++ pad_right = aligned_width - src_width; ++ pad_bot = aligned_height - src_height; ++ ++ if (param->conf_win_right > 0) ++ crop_right = param->conf_win_right + pad_right; ++ else ++ crop_right = pad_right; ++ ++ if (param->conf_win_bot > 0) ++ crop_bot = param->conf_win_bot + pad_bot; ++ else ++ crop_bot = pad_bot; ++ ++ crop_top = param->conf_win_top; ++ crop_left = param->conf_win_left; ++ ++ param->conf_win_top = crop_top; ++ param->conf_win_left = crop_left; ++ param->conf_win_bot = crop_bot; ++ param->conf_win_right = crop_right; ++ ++ switch (prp_mode) { ++ case 0: ++ return; ++ case 1: ++ case 15: ++ param->conf_win_top = crop_right; ++ param->conf_win_left = crop_top; ++ param->conf_win_bot = crop_left; ++ param->conf_win_right = crop_bot; ++ break; ++ case 2: ++ case 12: ++ param->conf_win_top = crop_bot; ++ param->conf_win_left = crop_right; ++ param->conf_win_bot = crop_top; ++ param->conf_win_right = crop_left; ++ break; ++ case 3: ++ case 13: ++ param->conf_win_top = crop_left; ++ param->conf_win_left = crop_bot; ++ param->conf_win_bot = crop_right; ++ param->conf_win_right = crop_top; ++ break; ++ case 4: ++ case 10: ++ param->conf_win_top = crop_bot; ++ param->conf_win_bot = crop_top; ++ break; ++ case 8: ++ case 6: ++ param->conf_win_left = crop_right; ++ param->conf_win_right = crop_left; ++ break; ++ case 5: ++ case 11: ++ param->conf_win_top = crop_left; ++ param->conf_win_left = crop_top; ++ param->conf_win_bot = crop_right; ++ param->conf_win_right = crop_bot; ++ break; ++ case 7: ++ case 9: ++ param->conf_win_top = crop_right; ++ param->conf_win_left = crop_bot; ++ param->conf_win_bot = crop_left; ++ param->conf_win_right = crop_top; ++ break; ++ default: ++ WARN(1, "Invalid prp_mode: %d, must be in range of 1 - 15\n", prp_mode); ++ } ++} ++ ++int wave5_vpu_enc_init_seq(struct vpu_instance *inst) ++{ ++ u32 reg_val = 0, rot_mir_mode, fixed_cu_size_mode = 0x7; ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ struct enc_open_param *p_open_param = &p_enc_info->open_param; ++ struct enc_wave_param *p_param = &p_open_param->wave_param; ++ ++ /* ++ * OPT_COMMON: ++ * the last SET_PARAM command should be called with OPT_COMMON ++ */ ++ rot_mir_mode = 0; ++ if (p_enc_info->rotation_enable) { ++ switch (p_enc_info->rotation_angle) { ++ case 0: ++ rot_mir_mode |= NONE_ROTATE; ++ break; ++ case 90: ++ rot_mir_mode |= ROT_CLOCKWISE_90; ++ break; ++ case 180: ++ rot_mir_mode |= ROT_CLOCKWISE_180; ++ break; ++ case 270: ++ rot_mir_mode |= ROT_CLOCKWISE_270; ++ break; ++ } ++ } ++ ++ if (p_enc_info->mirror_enable) { ++ switch (p_enc_info->mirror_direction) { ++ case MIRDIR_NONE: ++ rot_mir_mode |= NONE_ROTATE; ++ break; ++ case MIRDIR_VER: ++ rot_mir_mode |= MIR_VER_FLIP; ++ break; ++ case MIRDIR_HOR: ++ rot_mir_mode |= MIR_HOR_FLIP; ++ break; ++ case MIRDIR_HOR_VER: ++ rot_mir_mode |= MIR_HOR_VER_FLIP; ++ break; ++ } ++ } ++ ++ wave5_set_enc_crop_info(inst->std, p_param, rot_mir_mode, p_open_param->pic_width, ++ p_open_param->pic_height); ++ ++ /* SET_PARAM + COMMON */ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SET_PARAM_OPTION, OPT_COMMON); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SRC_SIZE, p_open_param->pic_height << 16 ++ | p_open_param->pic_width); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MAP_ENDIAN, VDI_LITTLE_ENDIAN); ++ ++ reg_val = p_param->profile | ++ (p_param->level << 3) | ++ (p_param->internal_bit_depth << 14); ++ if (inst->std == W_HEVC_ENC) ++ reg_val |= (p_param->tier << 12) | ++ (p_param->tmvp_enable << 23) | ++ (p_param->sao_enable << 24) | ++ (p_param->skip_intra_trans << 25) | ++ (p_param->strong_intra_smooth_enable << 27) | ++ (p_param->en_still_picture << 30); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SPS_PARAM, reg_val); ++ ++ reg_val = (p_param->lossless_enable) | ++ (p_param->const_intra_pred_flag << 1) | ++ (p_param->lf_cross_slice_boundary_enable << 2) | ++ (p_param->wpp_enable << 4) | ++ (p_param->disable_deblk << 5) | ++ ((p_param->beta_offset_div2 & 0xF) << 6) | ++ ((p_param->tc_offset_div2 & 0xF) << 10) | ++ ((p_param->chroma_cb_qp_offset & 0x1F) << 14) | ++ ((p_param->chroma_cr_qp_offset & 0x1F) << 19) | ++ (p_param->transform8x8_enable << 29) | ++ (p_param->entropy_coding_mode << 30); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_PPS_PARAM, reg_val); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_GOP_PARAM, p_param->gop_preset_idx); ++ ++ if (inst->std == W_AVC_ENC) ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_PARAM, p_param->intra_qp | ++ ((p_param->intra_period & 0x7ff) << 6) | ++ ((p_param->avc_idr_period & 0x7ff) << 17)); ++ else if (inst->std == W_HEVC_ENC) ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_PARAM, ++ p_param->decoding_refresh_type | (p_param->intra_qp << 3) | ++ (p_param->intra_period << 16)); ++ ++ reg_val = (p_param->rdo_skip << 2) | ++ (p_param->lambda_scaling_enable << 3) | ++ (fixed_cu_size_mode << 5) | ++ (p_param->intra_nx_n_enable << 8) | ++ (p_param->max_num_merge << 18); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RDO_PARAM, reg_val); ++ ++ if (inst->std == W_AVC_ENC) ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_REFRESH, ++ p_param->intra_mb_refresh_arg << 16 | p_param->intra_mb_refresh_mode); ++ else if (inst->std == W_HEVC_ENC) ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_REFRESH, ++ p_param->intra_refresh_arg << 16 | p_param->intra_refresh_mode); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_FRAME_RATE, p_open_param->frame_rate_info); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_TARGET_RATE, p_open_param->bit_rate); ++ ++ reg_val = p_open_param->rc_enable | ++ (p_param->hvs_qp_enable << 2) | ++ (p_param->hvs_qp_scale << 4) | ++ ((p_param->initial_rc_qp & 0x3F) << 14) | ++ (p_open_param->vbv_buffer_size << 20); ++ if (inst->std == W_AVC_ENC) ++ reg_val |= (p_param->mb_level_rc_enable << 1); ++ else if (inst->std == W_HEVC_ENC) ++ reg_val |= (p_param->cu_level_rc_enable << 1); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_PARAM, reg_val); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_WEIGHT_PARAM, ++ p_param->rc_weight_buf << 8 | p_param->rc_weight_param); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_MIN_MAX_QP, p_param->min_qp_i | ++ (p_param->max_qp_i << 6) | (p_param->hvs_max_delta_qp << 12)); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_INTER_MIN_MAX_QP, p_param->min_qp_p | ++ (p_param->max_qp_p << 6) | (p_param->min_qp_b << 12) | ++ (p_param->max_qp_b << 18)); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_0_3, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_4_7, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_ROT_PARAM, rot_mir_mode); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_BG_PARAM, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_LAMBDA_ADDR, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CONF_WIN_TOP_BOT, ++ p_param->conf_win_bot << 16 | p_param->conf_win_top); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CONF_WIN_LEFT_RIGHT, ++ p_param->conf_win_right << 16 | p_param->conf_win_left); ++ ++ if (inst->std == W_AVC_ENC) ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INDEPENDENT_SLICE, ++ p_param->avc_slice_arg << 16 | p_param->avc_slice_mode); ++ else if (inst->std == W_HEVC_ENC) ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INDEPENDENT_SLICE, ++ p_param->independ_slice_mode_arg << 16 | ++ p_param->independ_slice_mode); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_USER_SCALING_LIST_ADDR, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NUM_UNITS_IN_TICK, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_TIME_SCALE, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NUM_TICKS_POC_DIFF_ONE, 0); ++ ++ if (inst->std == W_HEVC_ENC) { ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU04, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU08, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU16, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU32, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU08, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU16, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU32, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_DEPENDENT_SLICE, ++ p_param->depend_slice_mode_arg << 16 | p_param->depend_slice_mode); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NR_PARAM, 0); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NR_WEIGHT, ++ p_param->nr_intra_weight_y | ++ (p_param->nr_intra_weight_cb << 5) | ++ (p_param->nr_intra_weight_cr << 10) | ++ (p_param->nr_inter_weight_y << 15) | ++ (p_param->nr_inter_weight_cb << 20) | ++ (p_param->nr_inter_weight_cr << 25)); ++ } ++ vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_VUI_HRD_PARAM, 0); ++ ++ return send_firmware_command(inst, W5_ENC_SET_PARAM, true, NULL, NULL); ++} ++ ++int wave5_vpu_enc_get_seq_info(struct vpu_instance *inst, struct enc_initial_info *info) ++{ ++ int ret; ++ u32 reg_val; ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ ++ /* send QUERY cmd */ ++ ret = wave5_send_query(inst->dev, inst, GET_RESULT); ++ if (ret) ++ return ret; ++ ++ dev_dbg(inst->dev->dev, "%s: init seq\n", __func__); ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS); ++ ++ p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff; ++ p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK); ++ ++ if (vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_SUCCESS) != 1) { ++ info->seq_init_err_reason = vpu_read_reg(inst->dev, W5_RET_ENC_ERR_INFO); ++ ret = -EIO; ++ } else { ++ info->warn_info = vpu_read_reg(inst->dev, W5_RET_ENC_WARN_INFO); ++ } ++ ++ info->min_frame_buffer_count = vpu_read_reg(inst->dev, W5_RET_ENC_NUM_REQUIRED_FB); ++ info->min_src_frame_count = vpu_read_reg(inst->dev, W5_RET_ENC_MIN_SRC_BUF_NUM); ++ info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE); ++ info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE); ++ p_enc_info->vlc_buf_size = info->vlc_buf_size; ++ p_enc_info->param_buf_size = info->param_buf_size; ++ ++ return ret; ++} ++ ++static u32 calculate_luma_stride(u32 width, u32 bit_depth) ++{ ++ return ALIGN(ALIGN(width, 16) * ((bit_depth > 8) ? 5 : 4), 32); ++} ++ ++static u32 calculate_chroma_stride(u32 width, u32 bit_depth) ++{ ++ return ALIGN(ALIGN(width / 2, 16) * ((bit_depth > 8) ? 5 : 4), 32); ++} ++ ++int wave5_vpu_enc_register_framebuffer(struct device *dev, struct vpu_instance *inst, ++ struct frame_buffer *fb_arr, enum tiled_map_type map_type, ++ unsigned int count) ++{ ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ int ret = 0; ++ u32 stride; ++ u32 start_no, end_no; ++ size_t remain, idx, j, i, cnt_8_chunk; ++ u32 reg_val = 0, pic_size = 0, mv_col_size, fbc_y_tbl_size, fbc_c_tbl_size; ++ u32 sub_sampled_size = 0; ++ u32 luma_stride, chroma_stride; ++ u32 buf_height = 0, buf_width = 0; ++ u32 bit_depth; ++ bool avc_encoding = (inst->std == W_AVC_ENC); ++ struct vpu_buf vb_mv = {0}; ++ struct vpu_buf vb_fbc_y_tbl = {0}; ++ struct vpu_buf vb_fbc_c_tbl = {0}; ++ struct vpu_buf vb_sub_sam_buf = {0}; ++ struct vpu_buf vb_task = {0}; ++ struct enc_open_param *p_open_param; ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ ++ p_open_param = &p_enc_info->open_param; ++ mv_col_size = 0; ++ fbc_y_tbl_size = 0; ++ fbc_c_tbl_size = 0; ++ stride = p_enc_info->stride; ++ bit_depth = p_open_param->wave_param.internal_bit_depth; ++ ++ if (avc_encoding) { ++ buf_width = ALIGN(p_open_param->pic_width, 16); ++ buf_height = ALIGN(p_open_param->pic_height, 16); ++ ++ if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) && ++ !(p_enc_info->rotation_angle == 180 && ++ p_enc_info->mirror_direction == MIRDIR_HOR_VER)) { ++ buf_width = ALIGN(p_open_param->pic_width, 16); ++ buf_height = ALIGN(p_open_param->pic_height, 16); ++ } ++ ++ if (p_enc_info->rotation_angle == 90 || p_enc_info->rotation_angle == 270) { ++ buf_width = ALIGN(p_open_param->pic_height, 16); ++ buf_height = ALIGN(p_open_param->pic_width, 16); ++ } ++ } else { ++ buf_width = ALIGN(p_open_param->pic_width, 8); ++ buf_height = ALIGN(p_open_param->pic_height, 8); ++ ++ if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) && ++ !(p_enc_info->rotation_angle == 180 && ++ p_enc_info->mirror_direction == MIRDIR_HOR_VER)) { ++ buf_width = ALIGN(p_open_param->pic_width, 32); ++ buf_height = ALIGN(p_open_param->pic_height, 32); ++ } ++ ++ if (p_enc_info->rotation_angle == 90 || p_enc_info->rotation_angle == 270) { ++ buf_width = ALIGN(p_open_param->pic_height, 32); ++ buf_height = ALIGN(p_open_param->pic_width, 32); ++ } ++ } ++ ++ pic_size = (buf_width << 16) | buf_height; ++ ++ if (avc_encoding) { ++ mv_col_size = WAVE5_ENC_AVC_BUF_SIZE(buf_width, buf_height); ++ vb_mv.daddr = 0; ++ vb_mv.size = ALIGN(mv_col_size * count, BUFFER_MARGIN) + BUFFER_MARGIN; ++ } else { ++ mv_col_size = WAVE5_ENC_HEVC_BUF_SIZE(buf_width, buf_height); ++ mv_col_size = ALIGN(mv_col_size, 16); ++ vb_mv.daddr = 0; ++ vb_mv.size = ALIGN(mv_col_size * count, BUFFER_MARGIN) + BUFFER_MARGIN; ++ } ++ ++ ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_mv); ++ if (ret) ++ return ret; ++ ++ p_enc_info->vb_mv = vb_mv; ++ ++ fbc_y_tbl_size = ALIGN(WAVE5_FBC_LUMA_TABLE_SIZE(buf_width, buf_height), 16); ++ fbc_c_tbl_size = ALIGN(WAVE5_FBC_CHROMA_TABLE_SIZE(buf_width, buf_height), 16); ++ ++ vb_fbc_y_tbl.daddr = 0; ++ vb_fbc_y_tbl.size = ALIGN(fbc_y_tbl_size * count, BUFFER_MARGIN) + BUFFER_MARGIN; ++ ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_fbc_y_tbl); ++ if (ret) ++ goto free_vb_fbc_y_tbl; ++ ++ p_enc_info->vb_fbc_y_tbl = vb_fbc_y_tbl; ++ ++ vb_fbc_c_tbl.daddr = 0; ++ vb_fbc_c_tbl.size = ALIGN(fbc_c_tbl_size * count, BUFFER_MARGIN) + BUFFER_MARGIN; ++ ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_fbc_c_tbl); ++ if (ret) ++ goto free_vb_fbc_c_tbl; ++ ++ p_enc_info->vb_fbc_c_tbl = vb_fbc_c_tbl; ++ ++ if (avc_encoding) ++ sub_sampled_size = WAVE5_SUBSAMPLED_ONE_SIZE_AVC(buf_width, buf_height); ++ else ++ sub_sampled_size = WAVE5_SUBSAMPLED_ONE_SIZE(buf_width, buf_height); ++ vb_sub_sam_buf.size = ALIGN(sub_sampled_size * count, BUFFER_MARGIN) + BUFFER_MARGIN; ++ vb_sub_sam_buf.daddr = 0; ++ ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_sub_sam_buf); ++ if (ret) ++ goto free_vb_sam_buf; ++ ++ p_enc_info->vb_sub_sam_buf = vb_sub_sam_buf; ++ ++ vb_task.size = (p_enc_info->vlc_buf_size * VLC_BUF_NUM) + ++ (p_enc_info->param_buf_size * COMMAND_QUEUE_DEPTH); ++ vb_task.daddr = 0; ++ if (p_enc_info->vb_task.size == 0) { ++ ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_task); ++ if (ret) ++ goto free_vb_task; ++ ++ p_enc_info->vb_task = vb_task; ++ ++ vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF, ++ p_enc_info->vb_task.daddr); ++ vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_task.size); ++ } ++ ++ /* set sub-sampled buffer base addr */ ++ vpu_write_reg(inst->dev, W5_ADDR_SUB_SAMPLED_FB_BASE, vb_sub_sam_buf.daddr); ++ /* set sub-sampled buffer size for one frame */ ++ vpu_write_reg(inst->dev, W5_SUB_SAMPLED_ONE_FB_SIZE, sub_sampled_size); ++ ++ vpu_write_reg(inst->dev, W5_PIC_SIZE, pic_size); ++ ++ /* set stride of luma/chroma for compressed buffer */ ++ if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) && ++ !(p_enc_info->rotation_angle == 180 && ++ p_enc_info->mirror_direction == MIRDIR_HOR_VER)) { ++ luma_stride = calculate_luma_stride(buf_width, bit_depth); ++ chroma_stride = calculate_chroma_stride(buf_width / 2, bit_depth); ++ } else { ++ luma_stride = calculate_luma_stride(p_open_param->pic_width, bit_depth); ++ chroma_stride = calculate_chroma_stride(p_open_param->pic_width / 2, bit_depth); ++ } ++ ++ vpu_write_reg(inst->dev, W5_FBC_STRIDE, luma_stride << 16 | chroma_stride); ++ vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, stride); ++ ++ remain = count; ++ cnt_8_chunk = DIV_ROUND_UP(count, 8); ++ idx = 0; ++ for (j = 0; j < cnt_8_chunk; j++) { ++ reg_val = (j == cnt_8_chunk - 1) << 4 | ((j == 0) << 3); ++ vpu_write_reg(inst->dev, W5_SFB_OPTION, reg_val); ++ start_no = j * 8; ++ end_no = start_no + ((remain >= 8) ? 8 : remain) - 1; ++ ++ vpu_write_reg(inst->dev, W5_SET_FB_NUM, (start_no << 8) | end_no); ++ ++ for (i = 0; i < 8 && i < remain; i++) { ++ vpu_write_reg(inst->dev, W5_ADDR_LUMA_BASE0 + (i << 4), fb_arr[i + ++ start_no].buf_y); ++ vpu_write_reg(inst->dev, W5_ADDR_CB_BASE0 + (i << 4), ++ fb_arr[i + start_no].buf_cb); ++ /* luma FBC offset table */ ++ vpu_write_reg(inst->dev, W5_ADDR_FBC_Y_OFFSET0 + (i << 4), ++ vb_fbc_y_tbl.daddr + idx * fbc_y_tbl_size); ++ /* chroma FBC offset table */ ++ vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4), ++ vb_fbc_c_tbl.daddr + idx * fbc_c_tbl_size); ++ ++ vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2), ++ vb_mv.daddr + idx * mv_col_size); ++ idx++; ++ } ++ remain -= i; ++ ++ ret = send_firmware_command(inst, W5_SET_FB, false, NULL, NULL); ++ if (ret) ++ goto free_vb_mem; ++ } ++ ++ ret = wave5_vpu_firmware_command_queue_error_check(vpu_dev, NULL); ++ if (ret) ++ goto free_vb_mem; ++ ++ return ret; ++ ++free_vb_mem: ++ wave5_vdi_free_dma_memory(vpu_dev, &vb_task); ++free_vb_task: ++ wave5_vdi_free_dma_memory(vpu_dev, &vb_sub_sam_buf); ++free_vb_sam_buf: ++ wave5_vdi_free_dma_memory(vpu_dev, &vb_fbc_c_tbl); ++free_vb_fbc_c_tbl: ++ wave5_vdi_free_dma_memory(vpu_dev, &vb_fbc_y_tbl); ++free_vb_fbc_y_tbl: ++ wave5_vdi_free_dma_memory(vpu_dev, &vb_mv); ++ return ret; ++} ++ ++int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res) ++{ ++ u32 src_frame_format; ++ u32 reg_val = 0; ++ u32 src_stride_c = 0; ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ struct frame_buffer *p_src_frame = option->source_frame; ++ struct enc_open_param *p_open_param = &p_enc_info->open_param; ++ bool justified = WTL_RIGHT_JUSTIFIED; ++ u32 format_no = WTL_PIXEL_8BIT; ++ int ret; ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_BS_START_ADDR, option->pic_stream_buffer_addr); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_BS_SIZE, option->pic_stream_buffer_size); ++ p_enc_info->stream_buf_start_addr = option->pic_stream_buffer_addr; ++ p_enc_info->stream_buf_size = option->pic_stream_buffer_size; ++ p_enc_info->stream_buf_end_addr = ++ option->pic_stream_buffer_addr + option->pic_stream_buffer_size; ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_AXI_SEL, DEFAULT_SRC_AXI); ++ /* secondary AXI */ ++ reg_val = (p_enc_info->sec_axi_info.use_enc_rdo_enable << 11) | ++ (p_enc_info->sec_axi_info.use_enc_lf_enable << 15); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_USE_SEC_AXI, reg_val); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_REPORT_PARAM, 0); ++ ++ /* ++ * CODEOPT_ENC_VCL is used to implicitly encode header/headers to generate bitstream. ++ * (use ENC_PUT_VIDEO_HEADER for give_command to encode only a header) ++ */ ++ if (option->code_option.implicit_header_encode) ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CODE_OPTION, ++ CODEOPT_ENC_HEADER_IMPLICIT | CODEOPT_ENC_VCL | ++ (option->code_option.encode_aud << 5) | ++ (option->code_option.encode_eos << 6) | ++ (option->code_option.encode_eob << 7)); ++ else ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CODE_OPTION, ++ option->code_option.implicit_header_encode | ++ (option->code_option.encode_vcl << 1) | ++ (option->code_option.encode_vps << 2) | ++ (option->code_option.encode_sps << 3) | ++ (option->code_option.encode_pps << 4) | ++ (option->code_option.encode_aud << 5) | ++ (option->code_option.encode_eos << 6) | ++ (option->code_option.encode_eob << 7)); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PIC_PARAM, 0); ++ ++ if (option->src_end_flag) ++ /* no more source images. */ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_PIC_IDX, 0xFFFFFFFF); ++ else ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_PIC_IDX, option->src_idx); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_Y, p_src_frame->buf_y); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_U, p_src_frame->buf_cb); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_V, p_src_frame->buf_cr); ++ ++ switch (p_open_param->src_format) { ++ case FORMAT_420: ++ case FORMAT_422: ++ case FORMAT_YUYV: ++ case FORMAT_YVYU: ++ case FORMAT_UYVY: ++ case FORMAT_VYUY: ++ justified = WTL_LEFT_JUSTIFIED; ++ format_no = WTL_PIXEL_8BIT; ++ src_stride_c = inst->cbcr_interleave ? p_src_frame->stride : ++ (p_src_frame->stride / 2); ++ src_stride_c = (p_open_param->src_format == FORMAT_422) ? src_stride_c * 2 : ++ src_stride_c; ++ break; ++ case FORMAT_420_P10_16BIT_MSB: ++ case FORMAT_422_P10_16BIT_MSB: ++ case FORMAT_YUYV_P10_16BIT_MSB: ++ case FORMAT_YVYU_P10_16BIT_MSB: ++ case FORMAT_UYVY_P10_16BIT_MSB: ++ case FORMAT_VYUY_P10_16BIT_MSB: ++ justified = WTL_RIGHT_JUSTIFIED; ++ format_no = WTL_PIXEL_16BIT; ++ src_stride_c = inst->cbcr_interleave ? p_src_frame->stride : ++ (p_src_frame->stride / 2); ++ src_stride_c = (p_open_param->src_format == ++ FORMAT_422_P10_16BIT_MSB) ? src_stride_c * 2 : src_stride_c; ++ break; ++ case FORMAT_420_P10_16BIT_LSB: ++ case FORMAT_422_P10_16BIT_LSB: ++ case FORMAT_YUYV_P10_16BIT_LSB: ++ case FORMAT_YVYU_P10_16BIT_LSB: ++ case FORMAT_UYVY_P10_16BIT_LSB: ++ case FORMAT_VYUY_P10_16BIT_LSB: ++ justified = WTL_LEFT_JUSTIFIED; ++ format_no = WTL_PIXEL_16BIT; ++ src_stride_c = inst->cbcr_interleave ? p_src_frame->stride : ++ (p_src_frame->stride / 2); ++ src_stride_c = (p_open_param->src_format == ++ FORMAT_422_P10_16BIT_LSB) ? src_stride_c * 2 : src_stride_c; ++ break; ++ case FORMAT_420_P10_32BIT_MSB: ++ case FORMAT_422_P10_32BIT_MSB: ++ case FORMAT_YUYV_P10_32BIT_MSB: ++ case FORMAT_YVYU_P10_32BIT_MSB: ++ case FORMAT_UYVY_P10_32BIT_MSB: ++ case FORMAT_VYUY_P10_32BIT_MSB: ++ justified = WTL_RIGHT_JUSTIFIED; ++ format_no = WTL_PIXEL_32BIT; ++ src_stride_c = inst->cbcr_interleave ? p_src_frame->stride : ++ ALIGN(p_src_frame->stride / 2, 16) * BIT(inst->cbcr_interleave); ++ src_stride_c = (p_open_param->src_format == ++ FORMAT_422_P10_32BIT_MSB) ? src_stride_c * 2 : src_stride_c; ++ break; ++ case FORMAT_420_P10_32BIT_LSB: ++ case FORMAT_422_P10_32BIT_LSB: ++ case FORMAT_YUYV_P10_32BIT_LSB: ++ case FORMAT_YVYU_P10_32BIT_LSB: ++ case FORMAT_UYVY_P10_32BIT_LSB: ++ case FORMAT_VYUY_P10_32BIT_LSB: ++ justified = WTL_LEFT_JUSTIFIED; ++ format_no = WTL_PIXEL_32BIT; ++ src_stride_c = inst->cbcr_interleave ? p_src_frame->stride : ++ ALIGN(p_src_frame->stride / 2, 16) * BIT(inst->cbcr_interleave); ++ src_stride_c = (p_open_param->src_format == ++ FORMAT_422_P10_32BIT_LSB) ? src_stride_c * 2 : src_stride_c; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ src_frame_format = (inst->cbcr_interleave << 1) | (inst->nv21); ++ switch (p_open_param->packed_format) { ++ case PACKED_YUYV: ++ src_frame_format = 4; ++ break; ++ case PACKED_YVYU: ++ src_frame_format = 5; ++ break; ++ case PACKED_UYVY: ++ src_frame_format = 6; ++ break; ++ case PACKED_VYUY: ++ src_frame_format = 7; ++ break; ++ default: ++ break; ++ } ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_STRIDE, ++ (p_src_frame->stride << 16) | src_stride_c); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_FORMAT, src_frame_format | ++ (format_no << 3) | (justified << 5) | (PIC_SRC_ENDIANNESS_BIG_ENDIAN << 6)); ++ ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_ADDR, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_PARAM, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_LONGTERM_PIC, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_Y, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_C, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_MEAN_Y, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_MEAN_C, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PREFIX_SEI_INFO, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PREFIX_SEI_NAL_ADDR, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SUFFIX_SEI_INFO, 0); ++ vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SUFFIX_SEI_NAL_ADDR, 0); ++ ++ ret = send_firmware_command(inst, W5_DEC_ENC_PIC, true, ®_val, fail_res); ++ if (ret == -ETIMEDOUT) ++ return ret; ++ ++ p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff; ++ p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK); ++ ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++int wave5_vpu_enc_get_result(struct vpu_instance *inst, struct enc_output_info *result) ++{ ++ int ret; ++ u32 encoding_success; ++ u32 reg_val; ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ ret = wave5_send_query(inst->dev, inst, GET_RESULT); ++ if (ret) ++ return ret; ++ ++ dev_dbg(inst->dev->dev, "%s: enc pic complete\n", __func__); ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS); ++ ++ p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff; ++ p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK); ++ ++ encoding_success = vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_SUCCESS); ++ if (!encoding_success) { ++ result->error_reason = vpu_read_reg(inst->dev, W5_RET_ENC_ERR_INFO); ++ return -EIO; ++ } ++ ++ result->warn_info = vpu_read_reg(inst->dev, W5_RET_ENC_WARN_INFO); ++ ++ reg_val = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_TYPE); ++ result->pic_type = reg_val & 0xFFFF; ++ ++ result->enc_vcl_nut = vpu_read_reg(inst->dev, W5_RET_ENC_VCL_NUT); ++ /* ++ * To get the reconstructed frame use the following index on ++ * inst->frame_buf ++ */ ++ result->recon_frame_index = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_IDX); ++ result->enc_pic_byte = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_BYTE); ++ result->enc_src_idx = vpu_read_reg(inst->dev, W5_RET_ENC_USED_SRC_IDX); ++ p_enc_info->stream_wr_ptr = vpu_read_reg(inst->dev, W5_RET_ENC_WR_PTR); ++ p_enc_info->stream_rd_ptr = vpu_read_reg(inst->dev, W5_RET_ENC_RD_PTR); ++ ++ result->bitstream_buffer = vpu_read_reg(inst->dev, W5_RET_ENC_RD_PTR); ++ result->rd_ptr = p_enc_info->stream_rd_ptr; ++ result->wr_ptr = p_enc_info->stream_wr_ptr; ++ ++ /*result for header only(no vcl) encoding */ ++ if (result->recon_frame_index == RECON_IDX_FLAG_HEADER_ONLY) ++ result->bitstream_size = result->enc_pic_byte; ++ else if (result->recon_frame_index < 0) ++ result->bitstream_size = 0; ++ else ++ result->bitstream_size = result->enc_pic_byte; ++ ++ result->enc_host_cmd_tick = vpu_read_reg(inst->dev, W5_RET_ENC_HOST_CMD_TICK); ++ result->enc_encode_end_tick = vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_END_TICK); ++ ++ if (!p_enc_info->first_cycle_check) { ++ result->frame_cycle = (result->enc_encode_end_tick - result->enc_host_cmd_tick) * ++ p_enc_info->cycle_per_tick; ++ p_enc_info->first_cycle_check = true; ++ } else { ++ result->frame_cycle = ++ (result->enc_encode_end_tick - vpu_dev->last_performance_cycles) * ++ p_enc_info->cycle_per_tick; ++ if (vpu_dev->last_performance_cycles < result->enc_host_cmd_tick) ++ result->frame_cycle = (result->enc_encode_end_tick - ++ result->enc_host_cmd_tick) * p_enc_info->cycle_per_tick; ++ } ++ vpu_dev->last_performance_cycles = result->enc_encode_end_tick; ++ ++ return 0; ++} ++ ++int wave5_vpu_enc_finish_seq(struct vpu_instance *inst, u32 *fail_res) ++{ ++ return send_firmware_command(inst, W5_DESTROY_INSTANCE, true, NULL, fail_res); ++} ++ ++static bool wave5_vpu_enc_check_common_param_valid(struct vpu_instance *inst, ++ struct enc_open_param *open_param) ++{ ++ bool low_delay = true; ++ struct enc_wave_param *param = &open_param->wave_param; ++ struct vpu_device *vpu_dev = inst->dev; ++ struct device *dev = vpu_dev->dev; ++ u32 num_ctu_row = (open_param->pic_height + 64 - 1) / 64; ++ u32 num_ctu_col = (open_param->pic_width + 64 - 1) / 64; ++ u32 ctu_sz = num_ctu_col * num_ctu_row; ++ ++ if (inst->std == W_HEVC_ENC && low_delay && ++ param->decoding_refresh_type == DEC_REFRESH_TYPE_CRA) { ++ dev_warn(dev, ++ "dec_refresh_type(CRA) shouldn't be used together with low delay GOP\n"); ++ dev_warn(dev, "Suggested configuration parameter: decoding refresh type (IDR)\n"); ++ param->decoding_refresh_type = 2; ++ } ++ ++ if (param->wpp_enable && param->independ_slice_mode) { ++ unsigned int num_ctb_in_width = ALIGN(open_param->pic_width, 64) >> 6; ++ ++ if (param->independ_slice_mode_arg % num_ctb_in_width) { ++ dev_err(dev, "independ_slice_mode_arg %u must be a multiple of %u\n", ++ param->independ_slice_mode_arg, num_ctb_in_width); ++ return false; ++ } ++ } ++ ++ /* multi-slice & wpp */ ++ if (param->wpp_enable && param->depend_slice_mode) { ++ dev_err(dev, "wpp_enable && depend_slice_mode cannot be used simultaneously\n"); ++ return false; ++ } ++ ++ if (!param->independ_slice_mode && param->depend_slice_mode) { ++ dev_err(dev, "depend_slice_mode requires independ_slice_mode\n"); ++ return false; ++ } else if (param->independ_slice_mode && ++ param->depend_slice_mode == DEPEND_SLICE_MODE_RECOMMENDED && ++ param->independ_slice_mode_arg < param->depend_slice_mode_arg) { ++ dev_err(dev, "independ_slice_mode_arg: %u must be smaller than %u\n", ++ param->independ_slice_mode_arg, param->depend_slice_mode_arg); ++ return false; ++ } ++ ++ if (param->independ_slice_mode && param->independ_slice_mode_arg > 65535) { ++ dev_err(dev, "independ_slice_mode_arg: %u must be smaller than 65535\n", ++ param->independ_slice_mode_arg); ++ return false; ++ } ++ ++ if (param->depend_slice_mode && param->depend_slice_mode_arg > 65535) { ++ dev_err(dev, "depend_slice_mode_arg: %u must be smaller than 65535\n", ++ param->depend_slice_mode_arg); ++ return false; ++ } ++ ++ if (param->conf_win_top % 2) { ++ dev_err(dev, "conf_win_top: %u, must be a multiple of 2\n", param->conf_win_top); ++ return false; ++ } ++ ++ if (param->conf_win_bot % 2) { ++ dev_err(dev, "conf_win_bot: %u, must be a multiple of 2\n", param->conf_win_bot); ++ return false; ++ } ++ ++ if (param->conf_win_left % 2) { ++ dev_err(dev, "conf_win_left: %u, must be a multiple of 2\n", param->conf_win_left); ++ return false; ++ } ++ ++ if (param->conf_win_right % 2) { ++ dev_err(dev, "conf_win_right: %u, Must be a multiple of 2\n", ++ param->conf_win_right); ++ return false; ++ } ++ ++ if (param->lossless_enable && open_param->rc_enable) { ++ dev_err(dev, "option rate_control cannot be used with lossless_coding\n"); ++ return false; ++ } ++ ++ if (param->lossless_enable && !param->skip_intra_trans) { ++ dev_err(dev, "option intra_trans_skip must be enabled with lossless_coding\n"); ++ return false; ++ } ++ ++ /* intra refresh */ ++ if (param->intra_refresh_mode && param->intra_refresh_arg == 0) { ++ dev_err(dev, "Invalid refresh argument, mode: %u, refresh: %u must be > 0\n", ++ param->intra_refresh_mode, param->intra_refresh_arg); ++ return false; ++ } ++ switch (param->intra_refresh_mode) { ++ case REFRESH_MODE_CTU_ROWS: ++ if (param->intra_mb_refresh_arg > num_ctu_row) ++ goto invalid_refresh_argument; ++ break; ++ case REFRESH_MODE_CTU_COLUMNS: ++ if (param->intra_refresh_arg > num_ctu_col) ++ goto invalid_refresh_argument; ++ break; ++ case REFRESH_MODE_CTU_STEP_SIZE: ++ if (param->intra_refresh_arg > ctu_sz) ++ goto invalid_refresh_argument; ++ break; ++ case REFRESH_MODE_CTUS: ++ if (param->intra_refresh_arg > ctu_sz) ++ goto invalid_refresh_argument; ++ if (param->lossless_enable) { ++ dev_err(dev, "mode: %u cannot be used lossless_enable", ++ param->intra_refresh_mode); ++ return false; ++ } ++ }; ++ return true; ++ ++invalid_refresh_argument: ++ dev_err(dev, "Invalid refresh argument, mode: %u, refresh: %u > W(%u)xH(%u)\n", ++ param->intra_refresh_mode, param->intra_refresh_arg, ++ num_ctu_row, num_ctu_col); ++ return false; ++} ++ ++static bool wave5_vpu_enc_check_param_valid(struct vpu_device *vpu_dev, ++ struct enc_open_param *open_param) ++{ ++ struct enc_wave_param *param = &open_param->wave_param; ++ ++ if (open_param->rc_enable) { ++ if (param->min_qp_i > param->max_qp_i || param->min_qp_p > param->max_qp_p || ++ param->min_qp_b > param->max_qp_b) { ++ dev_err(vpu_dev->dev, "Configuration failed because min_qp is greater than max_qp\n"); ++ dev_err(vpu_dev->dev, "Suggested configuration parameters: min_qp = max_qp\n"); ++ return false; ++ } ++ ++ if (open_param->bit_rate <= (int)open_param->frame_rate_info) { ++ dev_err(vpu_dev->dev, ++ "enc_bit_rate: %u must be greater than the frame_rate: %u\n", ++ open_param->bit_rate, (int)open_param->frame_rate_info); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++int wave5_vpu_enc_check_open_param(struct vpu_instance *inst, struct enc_open_param *open_param) ++{ ++ u32 pic_width; ++ u32 pic_height; ++ s32 product_id = inst->dev->product; ++ struct vpu_attr *p_attr = &inst->dev->attr; ++ struct enc_wave_param *param; ++ ++ if (!open_param) ++ return -EINVAL; ++ ++ param = &open_param->wave_param; ++ pic_width = open_param->pic_width; ++ pic_height = open_param->pic_height; ++ ++ if (inst->id >= MAX_NUM_INSTANCE) { ++ dev_err(inst->dev->dev, "Too many simultaneous instances: %d (max: %u)\n", ++ inst->id, MAX_NUM_INSTANCE); ++ return -EOPNOTSUPP; ++ } ++ ++ if (inst->std != W_HEVC_ENC && ++ !(inst->std == W_AVC_ENC && product_id == PRODUCT_ID_521)) { ++ dev_err(inst->dev->dev, "Unsupported encoder-codec & product combination\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (param->internal_bit_depth == 10) { ++ if (inst->std == W_HEVC_ENC && !p_attr->support_hevc10bit_enc) { ++ dev_err(inst->dev->dev, ++ "Flag support_hevc10bit_enc must be set to encode 10bit HEVC\n"); ++ return -EOPNOTSUPP; ++ } else if (inst->std == W_AVC_ENC && !p_attr->support_avc10bit_enc) { ++ dev_err(inst->dev->dev, ++ "Flag support_avc10bit_enc must be set to encode 10bit AVC\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ if (!open_param->frame_rate_info) { ++ dev_err(inst->dev->dev, "No frame rate information.\n"); ++ return -EINVAL; ++ } ++ ++ if (open_param->bit_rate > MAX_BIT_RATE) { ++ dev_err(inst->dev->dev, "Invalid encoding bit-rate: %u (valid: 0-%u)\n", ++ open_param->bit_rate, MAX_BIT_RATE); ++ return -EINVAL; ++ } ++ ++ if (pic_width < W5_MIN_ENC_PIC_WIDTH || pic_width > W5_MAX_ENC_PIC_WIDTH || ++ pic_height < W5_MIN_ENC_PIC_HEIGHT || pic_height > W5_MAX_ENC_PIC_HEIGHT) { ++ dev_err(inst->dev->dev, "Invalid encoding dimension: %ux%u\n", ++ pic_width, pic_height); ++ return -EINVAL; ++ } ++ ++ if (param->profile) { ++ if (inst->std == W_HEVC_ENC) { ++ if ((param->profile != HEVC_PROFILE_MAIN || ++ (param->profile == HEVC_PROFILE_MAIN && ++ param->internal_bit_depth > 8)) && ++ (param->profile != HEVC_PROFILE_MAIN10 || ++ (param->profile == HEVC_PROFILE_MAIN10 && ++ param->internal_bit_depth < 10)) && ++ param->profile != HEVC_PROFILE_STILLPICTURE) { ++ dev_err(inst->dev->dev, ++ "Invalid HEVC encoding profile: %u (bit-depth: %u)\n", ++ param->profile, param->internal_bit_depth); ++ return -EINVAL; ++ } ++ } else if (inst->std == W_AVC_ENC) { ++ if ((param->internal_bit_depth > 8 && ++ param->profile != H264_PROFILE_HIGH10)) { ++ dev_err(inst->dev->dev, ++ "Invalid AVC encoding profile: %u (bit-depth: %u)\n", ++ param->profile, param->internal_bit_depth); ++ return -EINVAL; ++ } ++ } ++ } ++ ++ if (param->decoding_refresh_type > DEC_REFRESH_TYPE_IDR) { ++ dev_err(inst->dev->dev, "Invalid decoding refresh type: %u (valid: 0-2)\n", ++ param->decoding_refresh_type); ++ return -EINVAL; ++ } ++ ++ if (param->intra_refresh_mode > REFRESH_MODE_CTUS) { ++ dev_err(inst->dev->dev, "Invalid intra refresh mode: %d (valid: 0-4)\n", ++ param->intra_refresh_mode); ++ return -EINVAL; ++ } ++ ++ if (inst->std == W_HEVC_ENC && param->independ_slice_mode && ++ param->depend_slice_mode > DEPEND_SLICE_MODE_BOOST) { ++ dev_err(inst->dev->dev, ++ "Can't combine slice modes: independent and fast dependent for HEVC\n"); ++ return -EINVAL; ++ } ++ ++ if (!param->disable_deblk) { ++ if (param->beta_offset_div2 < -6 || param->beta_offset_div2 > 6) { ++ dev_err(inst->dev->dev, "Invalid beta offset: %d (valid: -6-6)\n", ++ param->beta_offset_div2); ++ return -EINVAL; ++ } ++ ++ if (param->tc_offset_div2 < -6 || param->tc_offset_div2 > 6) { ++ dev_err(inst->dev->dev, "Invalid tc offset: %d (valid: -6-6)\n", ++ param->tc_offset_div2); ++ return -EINVAL; ++ } ++ } ++ ++ if (param->intra_qp > MAX_INTRA_QP) { ++ dev_err(inst->dev->dev, ++ "Invalid intra quantization parameter: %u (valid: 0-%u)\n", ++ param->intra_qp, MAX_INTRA_QP); ++ return -EINVAL; ++ } ++ ++ if (open_param->rc_enable) { ++ if (param->min_qp_i > MAX_INTRA_QP || param->max_qp_i > MAX_INTRA_QP || ++ param->min_qp_p > MAX_INTRA_QP || param->max_qp_p > MAX_INTRA_QP || ++ param->min_qp_b > MAX_INTRA_QP || param->max_qp_b > MAX_INTRA_QP) { ++ dev_err(inst->dev->dev, ++ "Invalid quantization parameter min/max values: " ++ "I: %u-%u, P: %u-%u, B: %u-%u (valid for each: 0-%u)\n", ++ param->min_qp_i, param->max_qp_i, param->min_qp_p, param->max_qp_p, ++ param->min_qp_b, param->max_qp_b, MAX_INTRA_QP); ++ return -EINVAL; ++ } ++ ++ if (param->hvs_qp_enable && param->hvs_max_delta_qp > MAX_HVS_MAX_DELTA_QP) { ++ dev_err(inst->dev->dev, ++ "Invalid HVS max delta quantization parameter: %u (valid: 0-%u)\n", ++ param->hvs_max_delta_qp, MAX_HVS_MAX_DELTA_QP); ++ return -EINVAL; ++ } ++ ++ if (open_param->vbv_buffer_size < MIN_VBV_BUFFER_SIZE || ++ open_param->vbv_buffer_size > MAX_VBV_BUFFER_SIZE) { ++ dev_err(inst->dev->dev, "VBV buffer size: %u (valid: %u-%u)\n", ++ open_param->vbv_buffer_size, MIN_VBV_BUFFER_SIZE, ++ MAX_VBV_BUFFER_SIZE); ++ return -EINVAL; ++ } ++ } ++ ++ if (!wave5_vpu_enc_check_common_param_valid(inst, open_param)) ++ return -EINVAL; ++ ++ if (!wave5_vpu_enc_check_param_valid(inst->dev, open_param)) ++ return -EINVAL; ++ ++ if (param->chroma_cb_qp_offset < -12 || param->chroma_cb_qp_offset > 12) { ++ dev_err(inst->dev->dev, ++ "Invalid chroma Cb quantization parameter offset: %d (valid: -12-12)\n", ++ param->chroma_cb_qp_offset); ++ return -EINVAL; ++ } ++ ++ if (param->chroma_cr_qp_offset < -12 || param->chroma_cr_qp_offset > 12) { ++ dev_err(inst->dev->dev, ++ "Invalid chroma Cr quantization parameter offset: %d (valid: -12-12)\n", ++ param->chroma_cr_qp_offset); ++ return -EINVAL; ++ } ++ ++ if (param->intra_refresh_mode == REFRESH_MODE_CTU_STEP_SIZE && !param->intra_refresh_arg) { ++ dev_err(inst->dev->dev, ++ "Intra refresh mode CTU step-size requires an argument\n"); ++ return -EINVAL; ++ } ++ ++ if (inst->std == W_HEVC_ENC) { ++ if (param->nr_intra_weight_y > MAX_INTRA_WEIGHT || ++ param->nr_intra_weight_cb > MAX_INTRA_WEIGHT || ++ param->nr_intra_weight_cr > MAX_INTRA_WEIGHT) { ++ dev_err(inst->dev->dev, ++ "Invalid intra weight Y(%u) Cb(%u) Cr(%u) (valid: %u)\n", ++ param->nr_intra_weight_y, param->nr_intra_weight_cb, ++ param->nr_intra_weight_cr, MAX_INTRA_WEIGHT); ++ return -EINVAL; ++ } ++ ++ if (param->nr_inter_weight_y > MAX_INTER_WEIGHT || ++ param->nr_inter_weight_cb > MAX_INTER_WEIGHT || ++ param->nr_inter_weight_cr > MAX_INTER_WEIGHT) { ++ dev_err(inst->dev->dev, ++ "Invalid inter weight Y(%u) Cb(%u) Cr(%u) (valid: %u)\n", ++ param->nr_inter_weight_y, param->nr_inter_weight_cb, ++ param->nr_inter_weight_cr, MAX_INTER_WEIGHT); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-regdefine.h b/drivers/media/platform/chips-media/wave5/wave5-regdefine.h +--- a/drivers/media/platform/chips-media/wave5/wave5-regdefine.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-regdefine.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,732 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ ++/* ++ * Wave5 series multi-standard codec IP - wave5 register definitions ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#ifndef __WAVE5_REGISTER_DEFINE_H__ ++#define __WAVE5_REGISTER_DEFINE_H__ ++ ++enum W5_VPU_COMMAND { ++ W5_INIT_VPU = 0x0001, ++ W5_WAKEUP_VPU = 0x0002, ++ W5_SLEEP_VPU = 0x0004, ++ W5_CREATE_INSTANCE = 0x0008, /* queuing command */ ++ W5_FLUSH_INSTANCE = 0x0010, ++ W5_DESTROY_INSTANCE = 0x0020, /* queuing command */ ++ W5_INIT_SEQ = 0x0040, /* queuing command */ ++ W5_SET_FB = 0x0080, ++ W5_DEC_ENC_PIC = 0x0100, /* queuing command */ ++ W5_ENC_SET_PARAM = 0x0200, /* queuing command */ ++ W5_QUERY = 0x4000, ++ W5_UPDATE_BS = 0x8000, ++ W5_MAX_VPU_COMD = 0x10000, ++}; ++ ++enum query_opt { ++ GET_VPU_INFO = 0, ++ SET_WRITE_PROT = 1, ++ GET_RESULT = 2, ++ UPDATE_DISP_FLAG = 3, ++ GET_BW_REPORT = 4, ++ GET_BS_RD_PTR = 5, /* for decoder */ ++ GET_BS_WR_PTR = 6, /* for encoder */ ++ GET_SRC_BUF_FLAG = 7, /* for encoder */ ++ SET_BS_RD_PTR = 8, /* for decoder */ ++ GET_DEBUG_INFO = 0x61, ++}; ++ ++#define W5_REG_BASE 0x00000000 ++#define W5_CMD_REG_BASE 0x00000100 ++#define W5_CMD_REG_END 0x00000200 ++ ++/* ++ * COMMON ++ * ++ * ---- ++ * ++ * Power on configuration ++ * PO_DEBUG_MODE [0] 1 - power on with debug mode ++ * USE_PO_CONF [3] 1 - use power-on-configuration ++ */ ++#define W5_PO_CONF (W5_REG_BASE + 0x0000) ++#define W5_VCPU_CUR_PC (W5_REG_BASE + 0x0004) ++#define W5_VCPU_CUR_LR (W5_REG_BASE + 0x0008) ++#define W5_VPU_PDBG_STEP_MASK_V (W5_REG_BASE + 0x000C) ++#define W5_VPU_PDBG_CTRL (W5_REG_BASE + 0x0010) /* v_cpu debugger ctrl register */ ++#define W5_VPU_PDBG_IDX_REG (W5_REG_BASE + 0x0014) /* v_cpu debugger index register */ ++#define W5_VPU_PDBG_WDATA_REG (W5_REG_BASE + 0x0018) /* v_cpu debugger write data reg */ ++#define W5_VPU_PDBG_RDATA_REG (W5_REG_BASE + 0x001C) /* v_cpu debugger read data reg */ ++ ++#define W5_VPU_FIO_CTRL_ADDR (W5_REG_BASE + 0x0020) ++#define W5_VPU_FIO_DATA (W5_REG_BASE + 0x0024) ++#define W5_VPU_VINT_REASON_USR (W5_REG_BASE + 0x0030) ++#define W5_VPU_VINT_REASON_CLR (W5_REG_BASE + 0x0034) ++#define W5_VPU_HOST_INT_REQ (W5_REG_BASE + 0x0038) ++#define W5_VPU_VINT_CLEAR (W5_REG_BASE + 0x003C) ++#define W5_VPU_HINT_CLEAR (W5_REG_BASE + 0x0040) ++#define W5_VPU_VPU_INT_STS (W5_REG_BASE + 0x0044) ++#define W5_VPU_VINT_ENABLE (W5_REG_BASE + 0x0048) ++#define W5_VPU_VINT_REASON (W5_REG_BASE + 0x004C) ++#define W5_VPU_RESET_REQ (W5_REG_BASE + 0x0050) ++#define W5_RST_BLOCK_CCLK(_core) BIT((_core)) ++#define W5_RST_BLOCK_CCLK_ALL (0xff) ++#define W5_RST_BLOCK_BCLK(_core) (0x100 << (_core)) ++#define W5_RST_BLOCK_BCLK_ALL (0xff00) ++#define W5_RST_BLOCK_ACLK(_core) (0x10000 << (_core)) ++#define W5_RST_BLOCK_ACLK_ALL (0xff0000) ++#define W5_RST_BLOCK_VCPU_ALL (0x3f000000) ++#define W5_RST_BLOCK_ALL (0x3fffffff) ++#define W5_VPU_RESET_STATUS (W5_REG_BASE + 0x0054) ++ ++#define W5_VCPU_RESTART (W5_REG_BASE + 0x0058) ++#define W5_VPU_CLK_MASK (W5_REG_BASE + 0x005C) ++ ++/* REMAP_CTRL ++ * PAGE SIZE: [8:0] 0x001 - 4K ++ * 0x002 - 8K ++ * 0x004 - 16K ++ * ... ++ * 0x100 - 1M ++ * REGION ATTR1 [10] 0 - normal ++ * 1 - make bus error for the region ++ * REGION ATTR2 [11] 0 - normal ++ * 1 - bypass region ++ * REMAP INDEX [15:12] - 0 ~ 3 ++ * ENDIAN [19:16] - NOTE: Currently not supported in this driver ++ * AXI-ID [23:20] - upper AXI-ID ++ * BUS_ERROR [29] 0 - bypass ++ * 1 - make BUS_ERROR for unmapped region ++ * BYPASS_ALL [30] 1 - bypass all ++ * ENABLE [31] 1 - update control register[30:16] ++ */ ++#define W5_VPU_REMAP_CTRL (W5_REG_BASE + 0x0060) ++#define W5_VPU_REMAP_VADDR (W5_REG_BASE + 0x0064) ++#define W5_VPU_REMAP_PADDR (W5_REG_BASE + 0x0068) ++#define W5_VPU_REMAP_CORE_START (W5_REG_BASE + 0x006C) ++#define W5_VPU_BUSY_STATUS (W5_REG_BASE + 0x0070) ++#define W5_VPU_HALT_STATUS (W5_REG_BASE + 0x0074) ++#define W5_VPU_VCPU_STATUS (W5_REG_BASE + 0x0078) ++#define W5_VPU_RET_PRODUCT_VERSION (W5_REG_BASE + 0x0094) ++/* ++ * assign vpu_config0 = {conf_map_converter_reg, // [31] ++ * conf_map_converter_sig, // [30] ++ * 8'd0, // [29:22] ++ * conf_std_switch_en, // [21] ++ * conf_bg_detect, // [20] ++ * conf_3dnr_en, // [19] ++ * conf_one_axi_en, // [18] ++ * conf_sec_axi_en, // [17] ++ * conf_bus_info, // [16] ++ * conf_afbc_en, // [15] ++ * conf_afbc_version_id, // [14:12] ++ * conf_fbc_en, // [11] ++ * conf_fbc_version_id, // [10:08] ++ * conf_scaler_en, // [07] ++ * conf_scaler_version_id, // [06:04] ++ * conf_bwb_en, // [03] ++ * 3'd0}; // [02:00] ++ */ ++#define W5_VPU_RET_VPU_CONFIG0 (W5_REG_BASE + 0x0098) ++/* ++ * assign vpu_config1 = {4'd0, // [31:28] ++ * conf_perf_timer_en, // [27] ++ * conf_multi_core_en, // [26] ++ * conf_gcu_en, // [25] ++ * conf_cu_report, // [24] ++ * 4'd0, // [23:20] ++ * conf_vcore_id_3, // [19] ++ * conf_vcore_id_2, // [18] ++ * conf_vcore_id_1, // [17] ++ * conf_vcore_id_0, // [16] ++ * conf_bwb_opt, // [15] ++ * 7'd0, // [14:08] ++ * conf_cod_std_en_reserved_7, // [7] ++ * conf_cod_std_en_reserved_6, // [6] ++ * conf_cod_std_en_reserved_5, // [5] ++ * conf_cod_std_en_reserved_4, // [4] ++ * conf_cod_std_en_reserved_3, // [3] ++ * conf_cod_std_en_reserved_2, // [2] ++ * conf_cod_std_en_vp9, // [1] ++ * conf_cod_std_en_hevc}; // [0] ++ * } ++ */ ++#define W5_VPU_RET_VPU_CONFIG1 (W5_REG_BASE + 0x009C) ++ ++#define W5_VPU_DBG_REG0 (W5_REG_BASE + 0x00f0) ++#define W5_VPU_DBG_REG1 (W5_REG_BASE + 0x00f4) ++#define W5_VPU_DBG_REG2 (W5_REG_BASE + 0x00f8) ++#define W5_VPU_DBG_REG3 (W5_REG_BASE + 0x00fc) ++ ++/************************************************************************/ ++/* PRODUCT INFORMATION */ ++/************************************************************************/ ++#define W5_PRODUCT_NAME (W5_REG_BASE + 0x1040) ++#define W5_PRODUCT_NUMBER (W5_REG_BASE + 0x1044) ++ ++/************************************************************************/ ++/* DECODER/ENCODER COMMON */ ++/************************************************************************/ ++#define W5_COMMAND (W5_REG_BASE + 0x0100) ++#define W5_COMMAND_OPTION (W5_REG_BASE + 0x0104) ++#define W5_QUERY_OPTION (W5_REG_BASE + 0x0104) ++#define W5_RET_SUCCESS (W5_REG_BASE + 0x0108) ++#define W5_RET_FAIL_REASON (W5_REG_BASE + 0x010C) ++#define W5_RET_QUEUE_FAIL_REASON (W5_REG_BASE + 0x0110) ++#define W5_CMD_INSTANCE_INFO (W5_REG_BASE + 0x0110) ++ ++#define W5_RET_QUEUE_STATUS (W5_REG_BASE + 0x01E0) ++#define W5_RET_BS_EMPTY_INST (W5_REG_BASE + 0x01E4) ++#define W5_RET_QUEUE_CMD_DONE_INST (W5_REG_BASE + 0x01E8) ++#define W5_RET_STAGE0_INSTANCE_INFO (W5_REG_BASE + 0x01EC) ++#define W5_RET_STAGE1_INSTANCE_INFO (W5_REG_BASE + 0x01F0) ++#define W5_RET_STAGE2_INSTANCE_INFO (W5_REG_BASE + 0x01F4) ++ ++#define W5_RET_SEQ_DONE_INSTANCE_INFO (W5_REG_BASE + 0x01FC) ++ ++#define W5_BS_OPTION (W5_REG_BASE + 0x0120) ++ ++/* return info when QUERY (GET_RESULT) for en/decoder */ ++#define W5_RET_VLC_BUF_SIZE (W5_REG_BASE + 0x01B0) ++/* return info when QUERY (GET_RESULT) for en/decoder */ ++#define W5_RET_PARAM_BUF_SIZE (W5_REG_BASE + 0x01B4) ++ ++/* set when SET_FB for en/decoder */ ++#define W5_CMD_SET_FB_ADDR_TASK_BUF (W5_REG_BASE + 0x01D4) ++#define W5_CMD_SET_FB_TASK_BUF_SIZE (W5_REG_BASE + 0x01D8) ++/************************************************************************/ ++/* INIT_VPU - COMMON */ ++/************************************************************************/ ++/* note: W5_ADDR_CODE_BASE should be aligned to 4KB */ ++#define W5_ADDR_CODE_BASE (W5_REG_BASE + 0x0110) ++#define W5_CODE_SIZE (W5_REG_BASE + 0x0114) ++#define W5_CODE_PARAM (W5_REG_BASE + 0x0118) ++#define W5_ADDR_TEMP_BASE (W5_REG_BASE + 0x011C) ++#define W5_TEMP_SIZE (W5_REG_BASE + 0x0120) ++#define W5_HW_OPTION (W5_REG_BASE + 0x012C) ++#define W5_SEC_AXI_PARAM (W5_REG_BASE + 0x0180) ++ ++/************************************************************************/ ++/* CREATE_INSTANCE - COMMON */ ++/************************************************************************/ ++#define W5_ADDR_WORK_BASE (W5_REG_BASE + 0x0114) ++#define W5_WORK_SIZE (W5_REG_BASE + 0x0118) ++#define W5_CMD_DEC_BS_START_ADDR (W5_REG_BASE + 0x011C) ++#define W5_CMD_DEC_BS_SIZE (W5_REG_BASE + 0x0120) ++#define W5_CMD_BS_PARAM (W5_REG_BASE + 0x0124) ++#define W5_CMD_ADDR_SEC_AXI (W5_REG_BASE + 0x0130) ++#define W5_CMD_SEC_AXI_SIZE (W5_REG_BASE + 0x0134) ++#define W5_CMD_EXT_ADDR (W5_REG_BASE + 0x0138) ++#define W5_CMD_NUM_CQ_DEPTH_M1 (W5_REG_BASE + 0x013C) ++#define W5_CMD_ERR_CONCEAL (W5_REG_BASE + 0x0140) ++ ++/************************************************************************/ ++/* DECODER - INIT_SEQ */ ++/************************************************************************/ ++#define W5_BS_RD_PTR (W5_REG_BASE + 0x0118) ++#define W5_BS_WR_PTR (W5_REG_BASE + 0x011C) ++/************************************************************************/ ++/* SET_FRAME_BUF */ ++/************************************************************************/ ++/* SET_FB_OPTION 0x00 REGISTER FRAMEBUFFERS ++ * 0x01 UPDATE FRAMEBUFFER, just one framebuffer(linear, fbc and mvcol) ++ */ ++#define W5_SFB_OPTION (W5_REG_BASE + 0x0104) ++#define W5_COMMON_PIC_INFO (W5_REG_BASE + 0x0118) ++#define W5_PIC_SIZE (W5_REG_BASE + 0x011C) ++#define W5_SET_FB_NUM (W5_REG_BASE + 0x0120) ++#define W5_EXTRA_PIC_INFO (W5_REG_BASE + 0x0124) ++ ++#define W5_ADDR_LUMA_BASE0 (W5_REG_BASE + 0x0134) ++#define W5_ADDR_CB_BASE0 (W5_REG_BASE + 0x0138) ++#define W5_ADDR_CR_BASE0 (W5_REG_BASE + 0x013C) ++/* compression offset table for luma */ ++#define W5_ADDR_FBC_Y_OFFSET0 (W5_REG_BASE + 0x013C) ++/* compression offset table for chroma */ ++#define W5_ADDR_FBC_C_OFFSET0 (W5_REG_BASE + 0x0140) ++#define W5_ADDR_LUMA_BASE1 (W5_REG_BASE + 0x0144) ++#define W5_ADDR_CB_ADDR1 (W5_REG_BASE + 0x0148) ++#define W5_ADDR_CR_ADDR1 (W5_REG_BASE + 0x014C) ++/* compression offset table for luma */ ++#define W5_ADDR_FBC_Y_OFFSET1 (W5_REG_BASE + 0x014C) ++/* compression offset table for chroma */ ++#define W5_ADDR_FBC_C_OFFSET1 (W5_REG_BASE + 0x0150) ++#define W5_ADDR_LUMA_BASE2 (W5_REG_BASE + 0x0154) ++#define W5_ADDR_CB_ADDR2 (W5_REG_BASE + 0x0158) ++#define W5_ADDR_CR_ADDR2 (W5_REG_BASE + 0x015C) ++/* compression offset table for luma */ ++#define W5_ADDR_FBC_Y_OFFSET2 (W5_REG_BASE + 0x015C) ++/* compression offset table for chroma */ ++#define W5_ADDR_FBC_C_OFFSET2 (W5_REG_BASE + 0x0160) ++#define W5_ADDR_LUMA_BASE3 (W5_REG_BASE + 0x0164) ++#define W5_ADDR_CB_ADDR3 (W5_REG_BASE + 0x0168) ++#define W5_ADDR_CR_ADDR3 (W5_REG_BASE + 0x016C) ++/* compression offset table for luma */ ++#define W5_ADDR_FBC_Y_OFFSET3 (W5_REG_BASE + 0x016C) ++/* compression offset table for chroma */ ++#define W5_ADDR_FBC_C_OFFSET3 (W5_REG_BASE + 0x0170) ++#define W5_ADDR_LUMA_BASE4 (W5_REG_BASE + 0x0174) ++#define W5_ADDR_CB_ADDR4 (W5_REG_BASE + 0x0178) ++#define W5_ADDR_CR_ADDR4 (W5_REG_BASE + 0x017C) ++/* compression offset table for luma */ ++#define W5_ADDR_FBC_Y_OFFSET4 (W5_REG_BASE + 0x017C) ++/* compression offset table for chroma */ ++#define W5_ADDR_FBC_C_OFFSET4 (W5_REG_BASE + 0x0180) ++#define W5_ADDR_LUMA_BASE5 (W5_REG_BASE + 0x0184) ++#define W5_ADDR_CB_ADDR5 (W5_REG_BASE + 0x0188) ++#define W5_ADDR_CR_ADDR5 (W5_REG_BASE + 0x018C) ++/* compression offset table for luma */ ++#define W5_ADDR_FBC_Y_OFFSET5 (W5_REG_BASE + 0x018C) ++/* compression offset table for chroma */ ++#define W5_ADDR_FBC_C_OFFSET5 (W5_REG_BASE + 0x0190) ++#define W5_ADDR_LUMA_BASE6 (W5_REG_BASE + 0x0194) ++#define W5_ADDR_CB_ADDR6 (W5_REG_BASE + 0x0198) ++#define W5_ADDR_CR_ADDR6 (W5_REG_BASE + 0x019C) ++/* compression offset table for luma */ ++#define W5_ADDR_FBC_Y_OFFSET6 (W5_REG_BASE + 0x019C) ++/* compression offset table for chroma */ ++#define W5_ADDR_FBC_C_OFFSET6 (W5_REG_BASE + 0x01A0) ++#define W5_ADDR_LUMA_BASE7 (W5_REG_BASE + 0x01A4) ++#define W5_ADDR_CB_ADDR7 (W5_REG_BASE + 0x01A8) ++#define W5_ADDR_CR_ADDR7 (W5_REG_BASE + 0x01AC) ++/* compression offset table for luma */ ++#define W5_ADDR_FBC_Y_OFFSET7 (W5_REG_BASE + 0x01AC) ++/* compression offset table for chroma */ ++#define W5_ADDR_FBC_C_OFFSET7 (W5_REG_BASE + 0x01B0) ++#define W5_ADDR_MV_COL0 (W5_REG_BASE + 0x01B4) ++#define W5_ADDR_MV_COL1 (W5_REG_BASE + 0x01B8) ++#define W5_ADDR_MV_COL2 (W5_REG_BASE + 0x01BC) ++#define W5_ADDR_MV_COL3 (W5_REG_BASE + 0x01C0) ++#define W5_ADDR_MV_COL4 (W5_REG_BASE + 0x01C4) ++#define W5_ADDR_MV_COL5 (W5_REG_BASE + 0x01C8) ++#define W5_ADDR_MV_COL6 (W5_REG_BASE + 0x01CC) ++#define W5_ADDR_MV_COL7 (W5_REG_BASE + 0x01D0) ++ ++/* UPDATE_FB */ ++/* CMD_SET_FB_STRIDE [15:0] - FBC framebuffer stride ++ * [31:15] - linear framebuffer stride ++ */ ++#define W5_CMD_SET_FB_STRIDE (W5_REG_BASE + 0x0118) ++#define W5_CMD_SET_FB_INDEX (W5_REG_BASE + 0x0120) ++#define W5_ADDR_LUMA_BASE (W5_REG_BASE + 0x0134) ++#define W5_ADDR_CB_BASE (W5_REG_BASE + 0x0138) ++#define W5_ADDR_CR_BASE (W5_REG_BASE + 0x013C) ++#define W5_ADDR_MV_COL (W5_REG_BASE + 0x0140) ++#define W5_ADDR_FBC_Y_BASE (W5_REG_BASE + 0x0144) ++#define W5_ADDR_FBC_C_BASE (W5_REG_BASE + 0x0148) ++#define W5_ADDR_FBC_Y_OFFSET (W5_REG_BASE + 0x014C) ++#define W5_ADDR_FBC_C_OFFSET (W5_REG_BASE + 0x0150) ++ ++/************************************************************************/ ++/* DECODER - DEC_PIC */ ++/************************************************************************/ ++#define W5_CMD_DEC_VCORE_INFO (W5_REG_BASE + 0x0194) ++/* sequence change enable mask register ++ * CMD_SEQ_CHANGE_ENABLE_FLAG [5] profile_idc ++ * [16] pic_width/height_in_luma_sample ++ * [19] sps_max_dec_pic_buffering, max_num_reorder, max_latency_increase ++ */ ++#define W5_CMD_SEQ_CHANGE_ENABLE_FLAG (W5_REG_BASE + 0x0128) ++#define W5_CMD_DEC_USER_MASK (W5_REG_BASE + 0x012C) ++#define W5_CMD_DEC_TEMPORAL_ID_PLUS1 (W5_REG_BASE + 0x0130) ++#define W5_CMD_DEC_FORCE_FB_LATENCY_PLUS1 (W5_REG_BASE + 0x0134) ++#define W5_USE_SEC_AXI (W5_REG_BASE + 0x0150) ++ ++/************************************************************************/ ++/* DECODER - QUERY : GET_VPU_INFO */ ++/************************************************************************/ ++#define W5_RET_FW_VERSION (W5_REG_BASE + 0x0118) ++#define W5_RET_PRODUCT_NAME (W5_REG_BASE + 0x011C) ++#define W5_RET_PRODUCT_VERSION (W5_REG_BASE + 0x0120) ++#define W5_RET_STD_DEF0 (W5_REG_BASE + 0x0124) ++#define W5_RET_STD_DEF1 (W5_REG_BASE + 0x0128) ++#define W5_RET_CONF_FEATURE (W5_REG_BASE + 0x012C) ++#define W5_RET_CONF_DATE (W5_REG_BASE + 0x0130) ++#define W5_RET_CONF_REVISION (W5_REG_BASE + 0x0134) ++#define W5_RET_CONF_TYPE (W5_REG_BASE + 0x0138) ++#define W5_RET_PRODUCT_ID (W5_REG_BASE + 0x013C) ++#define W5_RET_CUSTOMER_ID (W5_REG_BASE + 0x0140) ++ ++/************************************************************************/ ++/* DECODER - QUERY : GET_RESULT */ ++/************************************************************************/ ++#define W5_CMD_DEC_ADDR_REPORT_BASE (W5_REG_BASE + 0x0114) ++#define W5_CMD_DEC_REPORT_SIZE (W5_REG_BASE + 0x0118) ++#define W5_CMD_DEC_REPORT_PARAM (W5_REG_BASE + 0x011C) ++ ++#define W5_RET_DEC_BS_RD_PTR (W5_REG_BASE + 0x011C) ++#define W5_RET_DEC_SEQ_PARAM (W5_REG_BASE + 0x0120) ++#define W5_RET_DEC_COLOR_SAMPLE_INFO (W5_REG_BASE + 0x0124) ++#define W5_RET_DEC_ASPECT_RATIO (W5_REG_BASE + 0x0128) ++#define W5_RET_DEC_BIT_RATE (W5_REG_BASE + 0x012C) ++#define W5_RET_DEC_FRAME_RATE_NR (W5_REG_BASE + 0x0130) ++#define W5_RET_DEC_FRAME_RATE_DR (W5_REG_BASE + 0x0134) ++#define W5_RET_DEC_NUM_REQUIRED_FB (W5_REG_BASE + 0x0138) ++#define W5_RET_DEC_NUM_REORDER_DELAY (W5_REG_BASE + 0x013C) ++#define W5_RET_DEC_SUB_LAYER_INFO (W5_REG_BASE + 0x0140) ++#define W5_RET_DEC_NOTIFICATION (W5_REG_BASE + 0x0144) ++/* ++ * USER_DATA_FLAGS for HEVC/H264 only. ++ * Bits: ++ * [1] - User data buffer full boolean ++ * [2] - VUI parameter flag ++ * [4] - Pic_timing SEI flag ++ * [5] - 1st user_data_registed_itu_t_t35 prefix SEI flag ++ * [6] - user_data_unregistered prefix SEI flag ++ * [7] - 1st user_data_registed_itu_t_t35 suffix SEI flag ++ * [8] - user_data_unregistered suffix SEI flag ++ * [10]- mastering_display_color_volume prefix SEI flag ++ * [11]- chroma_resampling_display_color_volume prefix SEI flag ++ * [12]- knee_function_info SEI flag ++ * [13]- tone_mapping_info prefix SEI flag ++ * [14]- film_grain_characteristics_info prefix SEI flag ++ * [15]- content_light_level_info prefix SEI flag ++ * [16]- color_remapping_info prefix SEI flag ++ * [28]- 2nd user_data_registed_itu_t_t35 prefix SEI flag ++ * [29]- 3rd user_data_registed_itu_t_t35 prefix SEI flag ++ * [30]- 2nd user_data_registed_itu_t_t35 suffix SEI flag ++ * [31]- 3rd user_data_registed_itu_t_t35 suffix SEI flag ++ */ ++#define W5_RET_DEC_USERDATA_IDC (W5_REG_BASE + 0x0148) ++#define W5_RET_DEC_PIC_SIZE (W5_REG_BASE + 0x014C) ++#define W5_RET_DEC_CROP_TOP_BOTTOM (W5_REG_BASE + 0x0150) ++#define W5_RET_DEC_CROP_LEFT_RIGHT (W5_REG_BASE + 0x0154) ++/* ++ * #define W5_RET_DEC_AU_START_POS (W5_REG_BASE + 0x0158) ++ * => Access unit (AU) Bitstream start position ++ * #define W5_RET_DEC_AU_END_POS (W5_REG_BASE + 0x015C) ++ * => Access unit (AU) Bitstream end position ++ */ ++ ++/* ++ * Decoded picture type: ++ * reg_val & 0x7 => picture type ++ * (reg_val >> 4) & 0x3f => VCL NAL unit type ++ * (reg_val >> 31) & 0x1 => output_flag ++ * 16 << ((reg_val >> 10) & 0x3) => ctu_size ++ */ ++#define W5_RET_DEC_PIC_TYPE (W5_REG_BASE + 0x0160) ++#define W5_RET_DEC_PIC_POC (W5_REG_BASE + 0x0164) ++/* ++ * #define W5_RET_DEC_RECOVERY_POINT (W5_REG_BASE + 0x0168) ++ * => HEVC recovery point ++ * reg_val & 0xff => number of signed recovery picture order counts ++ * (reg_val >> 16) & 0x1 => exact match flag ++ * (reg_val >> 17) & 0x1 => broken link flag ++ * (reg_val >> 18) & 0x1 => exist flag ++ */ ++#define W5_RET_DEC_DEBUG_INDEX (W5_REG_BASE + 0x016C) ++#define W5_RET_DEC_DECODED_INDEX (W5_REG_BASE + 0x0170) ++#define W5_RET_DEC_DISPLAY_INDEX (W5_REG_BASE + 0x0174) ++/* ++ * #define W5_RET_DEC_REALLOC_INDEX (W5_REG_BASE + 0x0178) ++ * => display picture index in decoded picture buffer ++ * reg_val & 0xf => display picture index for FBC buffer (by reordering) ++ */ ++#define W5_RET_DEC_DISP_IDC (W5_REG_BASE + 0x017C) ++/* ++ * #define W5_RET_DEC_ERR_CTB_NUM (W5_REG_BASE + 0x0180) ++ * => Number of error CTUs ++ * reg_val >> 16 => erroneous CTUs in bitstream ++ * reg_val & 0xffff => total CTUs in bitstream ++ * ++ * #define W5_RET_DEC_PIC_PARAM (W5_REG_BASE + 0x01A0) ++ * => Bitstream sequence/picture parameter information (AV1 only) ++ * reg_val & 0x1 => intrabc tool enable ++ * (reg_val >> 1) & 0x1 => screen content tools enable ++ */ ++#define W5_RET_DEC_HOST_CMD_TICK (W5_REG_BASE + 0x01B8) ++/* ++ * #define W5_RET_DEC_SEEK_START_TICK (W5_REG_BASE + 0x01BC) ++ * #define W5_RET_DEC_SEEK_END_TICK (W5_REG_BASE + 0x01C0) ++ * => Start and end ticks for seeking slices of the picture ++ * #define W5_RET_DEC_PARSING_START_TICK (W5_REG_BASE + 0x01C4) ++ * #define W5_RET_DEC_PARSING_END_TICK (W5_REG_BASE + 0x01C8) ++ * => Start and end ticks for parsing slices of the picture ++ * #define W5_RET_DEC_DECODING_START_TICK (W5_REG_BASE + 0x01CC) ++ * => Start tick for decoding slices of the picture ++ */ ++#define W5_RET_DEC_DECODING_ENC_TICK (W5_REG_BASE + 0x01D0) ++#define W5_RET_DEC_WARN_INFO (W5_REG_BASE + 0x01D4) ++#define W5_RET_DEC_ERR_INFO (W5_REG_BASE + 0x01D8) ++#define W5_RET_DEC_DECODING_SUCCESS (W5_REG_BASE + 0x01DC) ++ ++/************************************************************************/ ++/* DECODER - FLUSH_INSTANCE */ ++/************************************************************************/ ++#define W5_CMD_FLUSH_INST_OPT (W5_REG_BASE + 0x104) ++ ++/************************************************************************/ ++/* DECODER - QUERY : UPDATE_DISP_FLAG */ ++/************************************************************************/ ++#define W5_CMD_DEC_SET_DISP_IDC (W5_REG_BASE + 0x0118) ++#define W5_CMD_DEC_CLR_DISP_IDC (W5_REG_BASE + 0x011C) ++ ++/************************************************************************/ ++/* DECODER - QUERY : SET_BS_RD_PTR */ ++/************************************************************************/ ++#define W5_RET_QUERY_DEC_SET_BS_RD_PTR (W5_REG_BASE + 0x011C) ++ ++/************************************************************************/ ++/* DECODER - QUERY : GET_BS_RD_PTR */ ++/************************************************************************/ ++#define W5_RET_QUERY_DEC_BS_RD_PTR (W5_REG_BASE + 0x011C) ++ ++/************************************************************************/ ++/* QUERY : GET_DEBUG_INFO */ ++/************************************************************************/ ++#define W5_RET_QUERY_DEBUG_PRI_REASON (W5_REG_BASE + 0x114) ++ ++/************************************************************************/ ++/* GDI register for debugging */ ++/************************************************************************/ ++#define W5_GDI_BASE 0x8800 ++#define W5_GDI_BUS_CTRL (W5_GDI_BASE + 0x0F0) ++#define W5_GDI_BUS_STATUS (W5_GDI_BASE + 0x0F4) ++ ++#define W5_BACKBONE_BASE_VCPU 0xFE00 ++#define W5_BACKBONE_BUS_CTRL_VCPU (W5_BACKBONE_BASE_VCPU + 0x010) ++#define W5_BACKBONE_BUS_STATUS_VCPU (W5_BACKBONE_BASE_VCPU + 0x014) ++#define W5_BACKBONE_PROG_AXI_ID (W5_BACKBONE_BASE_VCPU + 0x00C) ++ ++#define W5_BACKBONE_PROC_EXT_ADDR (W5_BACKBONE_BASE_VCPU + 0x0C0) ++#define W5_BACKBONE_AXI_PARAM (W5_BACKBONE_BASE_VCPU + 0x0E0) ++ ++#define W5_BACKBONE_BASE_VCORE0 0x8E00 ++#define W5_BACKBONE_BUS_CTRL_VCORE0 (W5_BACKBONE_BASE_VCORE0 + 0x010) ++#define W5_BACKBONE_BUS_STATUS_VCORE0 (W5_BACKBONE_BASE_VCORE0 + 0x014) ++ ++#define W5_BACKBONE_BASE_VCORE1 0x9E00 /* for dual-core product */ ++#define W5_BACKBONE_BUS_CTRL_VCORE1 (W5_BACKBONE_BASE_VCORE1 + 0x010) ++#define W5_BACKBONE_BUS_STATUS_VCORE1 (W5_BACKBONE_BASE_VCORE1 + 0x014) ++ ++#define W5_COMBINED_BACKBONE_BASE 0xFE00 ++#define W5_COMBINED_BACKBONE_BUS_CTRL (W5_COMBINED_BACKBONE_BASE + 0x010) ++#define W5_COMBINED_BACKBONE_BUS_STATUS (W5_COMBINED_BACKBONE_BASE + 0x014) ++ ++/************************************************************************/ ++/* */ ++/* for ENCODER */ ++/* */ ++/************************************************************************/ ++#define W5_RET_STAGE3_INSTANCE_INFO (W5_REG_BASE + 0x1F8) ++/************************************************************************/ ++/* ENCODER - CREATE_INSTANCE */ ++/************************************************************************/ ++/* 0x114 ~ 0x124 : defined above (CREATE_INSTANCE COMMON) */ ++#define W5_CMD_ENC_VCORE_INFO (W5_REG_BASE + 0x0194) ++#define W5_CMD_ENC_SRC_OPTIONS (W5_REG_BASE + 0x0128) ++ ++/************************************************************************/ ++/* ENCODER - SET_FB */ ++/************************************************************************/ ++#define W5_FBC_STRIDE (W5_REG_BASE + 0x128) ++#define W5_ADDR_SUB_SAMPLED_FB_BASE (W5_REG_BASE + 0x12C) ++#define W5_SUB_SAMPLED_ONE_FB_SIZE (W5_REG_BASE + 0x130) ++ ++/************************************************************************/ ++/* ENCODER - ENC_SET_PARAM (COMMON & CHANGE_PARAM) */ ++/************************************************************************/ ++#define W5_CMD_ENC_SEQ_SET_PARAM_OPTION (W5_REG_BASE + 0x104) ++#define W5_CMD_ENC_SEQ_SET_PARAM_ENABLE (W5_REG_BASE + 0x118) ++#define W5_CMD_ENC_SEQ_SRC_SIZE (W5_REG_BASE + 0x11C) ++#define W5_CMD_ENC_SEQ_CUSTOM_MAP_ENDIAN (W5_REG_BASE + 0x120) ++#define W5_CMD_ENC_SEQ_SPS_PARAM (W5_REG_BASE + 0x124) ++#define W5_CMD_ENC_SEQ_PPS_PARAM (W5_REG_BASE + 0x128) ++#define W5_CMD_ENC_SEQ_GOP_PARAM (W5_REG_BASE + 0x12C) ++#define W5_CMD_ENC_SEQ_INTRA_PARAM (W5_REG_BASE + 0x130) ++#define W5_CMD_ENC_SEQ_CONF_WIN_TOP_BOT (W5_REG_BASE + 0x134) ++#define W5_CMD_ENC_SEQ_CONF_WIN_LEFT_RIGHT (W5_REG_BASE + 0x138) ++#define W5_CMD_ENC_SEQ_RDO_PARAM (W5_REG_BASE + 0x13C) ++#define W5_CMD_ENC_SEQ_INDEPENDENT_SLICE (W5_REG_BASE + 0x140) ++#define W5_CMD_ENC_SEQ_DEPENDENT_SLICE (W5_REG_BASE + 0x144) ++#define W5_CMD_ENC_SEQ_INTRA_REFRESH (W5_REG_BASE + 0x148) ++#define W5_CMD_ENC_SEQ_INPUT_SRC_PARAM (W5_REG_BASE + 0x14C) ++ ++#define W5_CMD_ENC_SEQ_RC_FRAME_RATE (W5_REG_BASE + 0x150) ++#define W5_CMD_ENC_SEQ_RC_TARGET_RATE (W5_REG_BASE + 0x154) ++#define W5_CMD_ENC_SEQ_RC_PARAM (W5_REG_BASE + 0x158) ++#define W5_CMD_ENC_SEQ_RC_MIN_MAX_QP (W5_REG_BASE + 0x15C) ++#define W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_0_3 (W5_REG_BASE + 0x160) ++#define W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_4_7 (W5_REG_BASE + 0x164) ++#define W5_CMD_ENC_SEQ_RC_INTER_MIN_MAX_QP (W5_REG_BASE + 0x168) ++#define W5_CMD_ENC_SEQ_RC_WEIGHT_PARAM (W5_REG_BASE + 0x16C) ++ ++#define W5_CMD_ENC_SEQ_ROT_PARAM (W5_REG_BASE + 0x170) ++#define W5_CMD_ENC_SEQ_NUM_UNITS_IN_TICK (W5_REG_BASE + 0x174) ++#define W5_CMD_ENC_SEQ_TIME_SCALE (W5_REG_BASE + 0x178) ++#define W5_CMD_ENC_SEQ_NUM_TICKS_POC_DIFF_ONE (W5_REG_BASE + 0x17C) ++ ++#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU04 (W5_REG_BASE + 0x184) ++#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU08 (W5_REG_BASE + 0x188) ++#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU16 (W5_REG_BASE + 0x18C) ++#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU32 (W5_REG_BASE + 0x190) ++#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU08 (W5_REG_BASE + 0x194) ++#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU16 (W5_REG_BASE + 0x198) ++#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU32 (W5_REG_BASE + 0x19C) ++#define W5_CMD_ENC_SEQ_NR_PARAM (W5_REG_BASE + 0x1A0) ++#define W5_CMD_ENC_SEQ_NR_WEIGHT (W5_REG_BASE + 0x1A4) ++#define W5_CMD_ENC_SEQ_BG_PARAM (W5_REG_BASE + 0x1A8) ++#define W5_CMD_ENC_SEQ_CUSTOM_LAMBDA_ADDR (W5_REG_BASE + 0x1AC) ++#define W5_CMD_ENC_SEQ_USER_SCALING_LIST_ADDR (W5_REG_BASE + 0x1B0) ++#define W5_CMD_ENC_SEQ_VUI_HRD_PARAM (W5_REG_BASE + 0x180) ++#define W5_CMD_ENC_SEQ_VUI_RBSP_ADDR (W5_REG_BASE + 0x1B8) ++#define W5_CMD_ENC_SEQ_HRD_RBSP_ADDR (W5_REG_BASE + 0x1BC) ++ ++/************************************************************************/ ++/* ENCODER - ENC_SET_PARAM (CUSTOM_GOP) */ ++/************************************************************************/ ++#define W5_CMD_ENC_CUSTOM_GOP_PARAM (W5_REG_BASE + 0x11C) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_0 (W5_REG_BASE + 0x120) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_1 (W5_REG_BASE + 0x124) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_2 (W5_REG_BASE + 0x128) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_3 (W5_REG_BASE + 0x12C) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_4 (W5_REG_BASE + 0x130) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_5 (W5_REG_BASE + 0x134) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_6 (W5_REG_BASE + 0x138) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_7 (W5_REG_BASE + 0x13C) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_8 (W5_REG_BASE + 0x140) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_9 (W5_REG_BASE + 0x144) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_10 (W5_REG_BASE + 0x148) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_11 (W5_REG_BASE + 0x14C) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_12 (W5_REG_BASE + 0x150) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_13 (W5_REG_BASE + 0x154) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_14 (W5_REG_BASE + 0x158) ++#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_15 (W5_REG_BASE + 0x15C) ++ ++/************************************************************************/ ++/* ENCODER - ENC_PIC */ ++/************************************************************************/ ++#define W5_CMD_ENC_BS_START_ADDR (W5_REG_BASE + 0x118) ++#define W5_CMD_ENC_BS_SIZE (W5_REG_BASE + 0x11C) ++#define W5_CMD_ENC_PIC_USE_SEC_AXI (W5_REG_BASE + 0x124) ++#define W5_CMD_ENC_PIC_REPORT_PARAM (W5_REG_BASE + 0x128) ++ ++#define W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_PARAM (W5_REG_BASE + 0x138) ++#define W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_ADDR (W5_REG_BASE + 0x13C) ++#define W5_CMD_ENC_PIC_SRC_PIC_IDX (W5_REG_BASE + 0x144) ++#define W5_CMD_ENC_PIC_SRC_ADDR_Y (W5_REG_BASE + 0x148) ++#define W5_CMD_ENC_PIC_SRC_ADDR_U (W5_REG_BASE + 0x14C) ++#define W5_CMD_ENC_PIC_SRC_ADDR_V (W5_REG_BASE + 0x150) ++#define W5_CMD_ENC_PIC_SRC_STRIDE (W5_REG_BASE + 0x154) ++#define W5_CMD_ENC_PIC_SRC_FORMAT (W5_REG_BASE + 0x158) ++#define W5_CMD_ENC_PIC_SRC_AXI_SEL (W5_REG_BASE + 0x160) ++#define W5_CMD_ENC_PIC_CODE_OPTION (W5_REG_BASE + 0x164) ++#define W5_CMD_ENC_PIC_PIC_PARAM (W5_REG_BASE + 0x168) ++#define W5_CMD_ENC_PIC_LONGTERM_PIC (W5_REG_BASE + 0x16C) ++#define W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_Y (W5_REG_BASE + 0x170) ++#define W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_C (W5_REG_BASE + 0x174) ++#define W5_CMD_ENC_PIC_WP_PIXEL_MEAN_Y (W5_REG_BASE + 0x178) ++#define W5_CMD_ENC_PIC_WP_PIXEL_MEAN_C (W5_REG_BASE + 0x17C) ++#define W5_CMD_ENC_PIC_CF50_Y_OFFSET_TABLE_ADDR (W5_REG_BASE + 0x190) ++#define W5_CMD_ENC_PIC_CF50_CB_OFFSET_TABLE_ADDR (W5_REG_BASE + 0x194) ++#define W5_CMD_ENC_PIC_CF50_CR_OFFSET_TABLE_ADDR (W5_REG_BASE + 0x198) ++#define W5_CMD_ENC_PIC_PREFIX_SEI_NAL_ADDR (W5_REG_BASE + 0x180) ++#define W5_CMD_ENC_PIC_PREFIX_SEI_INFO (W5_REG_BASE + 0x184) ++#define W5_CMD_ENC_PIC_SUFFIX_SEI_NAL_ADDR (W5_REG_BASE + 0x188) ++#define W5_CMD_ENC_PIC_SUFFIX_SEI_INFO (W5_REG_BASE + 0x18c) ++ ++/************************************************************************/ ++/* ENCODER - QUERY (GET_RESULT) */ ++/************************************************************************/ ++#define W5_RET_ENC_NUM_REQUIRED_FB (W5_REG_BASE + 0x11C) ++#define W5_RET_ENC_MIN_SRC_BUF_NUM (W5_REG_BASE + 0x120) ++#define W5_RET_ENC_PIC_TYPE (W5_REG_BASE + 0x124) ++/* ++ * #define W5_RET_ENC_PIC_POC (W5_REG_BASE + 0x128) ++ * => picture order count value of current encoded picture ++ */ ++#define W5_RET_ENC_PIC_IDX (W5_REG_BASE + 0x12C) ++/* ++ * #define W5_RET_ENC_PIC_SLICE_NUM (W5_REG_BASE + 0x130) ++ * reg_val & 0xffff = total independent slice segment number (16 bits) ++ * (reg_val >> 16) & 0xffff = total dependent slice segment number (16 bits) ++ * ++ * #define W5_RET_ENC_PIC_SKIP (W5_REG_BASE + 0x134) ++ * reg_val & 0xfe = picture skip flag (7 bits) ++ * ++ * #define W5_RET_ENC_PIC_NUM_INTRA (W5_REG_BASE + 0x138) ++ * => number of intra blocks in 8x8 (32 bits) ++ * ++ * #define W5_RET_ENC_PIC_NUM_MERGE (W5_REG_BASE + 0x13C) ++ * => number of merge blocks in 8x8 (32 bits) ++ * ++ * #define W5_RET_ENC_PIC_NUM_SKIP (W5_REG_BASE + 0x144) ++ * => number of skip blocks in 8x8 (32 bits) ++ * ++ * #define W5_RET_ENC_PIC_AVG_CTU_QP (W5_REG_BASE + 0x148) ++ * => Average CTU QP value (32 bits) ++ */ ++#define W5_RET_ENC_PIC_BYTE (W5_REG_BASE + 0x14C) ++/* ++ * #define W5_RET_ENC_GOP_PIC_IDX (W5_REG_BASE + 0x150) ++ * => picture index in group of pictures ++ */ ++#define W5_RET_ENC_USED_SRC_IDX (W5_REG_BASE + 0x154) ++/* ++ * #define W5_RET_ENC_PIC_NUM (W5_REG_BASE + 0x158) ++ * => encoded picture number ++ */ ++#define W5_RET_ENC_VCL_NUT (W5_REG_BASE + 0x15C) ++/* ++ * Only for H264: ++ * #define W5_RET_ENC_PIC_DIST_LOW (W5_REG_BASE + 0x164) ++ * => lower 32 bits of the sum of squared difference between source Y picture ++ * and reconstructed Y picture ++ * #define W5_RET_ENC_PIC_DIST_HIGH (W5_REG_BASE + 0x168) ++ * => upper 32 bits of the sum of squared difference between source Y picture ++ * and reconstructed Y picture ++ */ ++#define W5_RET_ENC_PIC_MAX_LATENCY_PICS (W5_REG_BASE + 0x16C) ++ ++#define W5_RET_ENC_HOST_CMD_TICK (W5_REG_BASE + 0x1B8) ++/* ++ * #define W5_RET_ENC_PREPARE_START_TICK (W5_REG_BASE + 0x1BC) ++ * #define W5_RET_ENC_PREPARE_END_TICK (W5_REG_BASE + 0x1C0) ++ * => Start and end ticks for preparing slices of the picture ++ * #define W5_RET_ENC_PROCESSING_START_TICK (W5_REG_BASE + 0x1C4) ++ * #define W5_RET_ENC_PROCESSING_END_TICK (W5_REG_BASE + 0x1C8) ++ * => Start and end ticks for processing slices of the picture ++ * #define W5_RET_ENC_ENCODING_START_TICK (W5_REG_BASE + 0x1CC) ++ * => Start tick for encoding slices of the picture ++ */ ++#define W5_RET_ENC_ENCODING_END_TICK (W5_REG_BASE + 0x1D0) ++ ++#define W5_RET_ENC_WARN_INFO (W5_REG_BASE + 0x1D4) ++#define W5_RET_ENC_ERR_INFO (W5_REG_BASE + 0x1D8) ++#define W5_RET_ENC_ENCODING_SUCCESS (W5_REG_BASE + 0x1DC) ++ ++/************************************************************************/ ++/* ENCODER - QUERY (GET_BS_WR_PTR) */ ++/************************************************************************/ ++#define W5_RET_ENC_RD_PTR (W5_REG_BASE + 0x114) ++#define W5_RET_ENC_WR_PTR (W5_REG_BASE + 0x118) ++#define W5_CMD_ENC_REASON_SEL (W5_REG_BASE + 0x11C) ++ ++/************************************************************************/ ++/* ENCODER - QUERY (GET_BW_REPORT) */ ++/************************************************************************/ ++#define RET_QUERY_BW_PRP_AXI_READ (W5_REG_BASE + 0x118) ++#define RET_QUERY_BW_PRP_AXI_WRITE (W5_REG_BASE + 0x11C) ++#define RET_QUERY_BW_FBD_Y_AXI_READ (W5_REG_BASE + 0x120) ++#define RET_QUERY_BW_FBC_Y_AXI_WRITE (W5_REG_BASE + 0x124) ++#define RET_QUERY_BW_FBD_C_AXI_READ (W5_REG_BASE + 0x128) ++#define RET_QUERY_BW_FBC_C_AXI_WRITE (W5_REG_BASE + 0x12C) ++#define RET_QUERY_BW_PRI_AXI_READ (W5_REG_BASE + 0x130) ++#define RET_QUERY_BW_PRI_AXI_WRITE (W5_REG_BASE + 0x134) ++#define RET_QUERY_BW_SEC_AXI_READ (W5_REG_BASE + 0x138) ++#define RET_QUERY_BW_SEC_AXI_WRITE (W5_REG_BASE + 0x13C) ++#define RET_QUERY_BW_PROC_AXI_READ (W5_REG_BASE + 0x140) ++#define RET_QUERY_BW_PROC_AXI_WRITE (W5_REG_BASE + 0x144) ++#define RET_QUERY_BW_BWB_AXI_WRITE (W5_REG_BASE + 0x148) ++#define W5_CMD_BW_OPTION (W5_REG_BASE + 0x14C) ++ ++/************************************************************************/ ++/* ENCODER - QUERY (GET_SRC_FLAG) */ ++/************************************************************************/ ++#define W5_RET_RELEASED_SRC_INSTANCE (W5_REG_BASE + 0x1EC) ++ ++#define W5_ENC_PIC_SUB_FRAME_SYNC_IF (W5_REG_BASE + 0x0300) ++ ++#endif /* __WAVE5_REGISTER_DEFINE_H__ */ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vdi.c b/drivers/media/platform/chips-media/wave5/wave5-vdi.c +--- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,205 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) ++/* ++ * Wave5 series multi-standard codec IP - low level access functions ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#include ++#include "wave5-vdi.h" ++#include "wave5-vpu.h" ++#include "wave5-regdefine.h" ++#include ++ ++static int wave5_vdi_allocate_common_memory(struct device *dev) ++{ ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ ++ if (!vpu_dev->common_mem.vaddr) { ++ int ret; ++ ++ vpu_dev->common_mem.size = SIZE_COMMON; ++ ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev->common_mem); ++ if (ret) { ++ dev_err(dev, "unable to allocate common buffer\n"); ++ return ret; ++ } ++ } ++ ++ dev_dbg(dev, "[VDI] common_mem: daddr=%pad size=%zu vaddr=0x%p\n", ++ &vpu_dev->common_mem.daddr, vpu_dev->common_mem.size, vpu_dev->common_mem.vaddr); ++ ++ return 0; ++} ++ ++int wave5_vdi_init(struct device *dev) ++{ ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = wave5_vdi_allocate_common_memory(dev); ++ if (ret < 0) { ++ dev_err(dev, "[VDI] failed to get vpu common buffer from driver\n"); ++ return ret; ++ } ++ ++ if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) { ++ WARN_ONCE(1, "unsupported product code: 0x%x\n", vpu_dev->product_code); ++ return -EOPNOTSUPP; ++ } ++ ++ /* if BIT processor is not running. */ ++ if (wave5_vdi_read_register(vpu_dev, W5_VCPU_CUR_PC) == 0) { ++ int i; ++ ++ for (i = 0; i < 64; i++) ++ wave5_vdi_write_register(vpu_dev, (i * 4) + 0x100, 0x0); ++ } ++ ++ dev_dbg(dev, "[VDI] driver initialized successfully\n"); ++ ++ return 0; ++} ++ ++int wave5_vdi_release(struct device *dev) ++{ ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ ++ vpu_dev->vdb_register = NULL; ++ wave5_vdi_free_dma_memory(vpu_dev, &vpu_dev->common_mem); ++ ++ return 0; ++} ++ ++void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data) ++{ ++ writel(data, vpu_dev->vdb_register + addr); ++} ++ ++unsigned int wave5_vdi_read_register(struct vpu_device *vpu_dev, u32 addr) ++{ ++ return readl(vpu_dev->vdb_register + addr); ++} ++ ++int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) ++{ ++ if (!vb || !vb->vaddr) { ++ dev_err(vpu_dev->dev, "%s: unable to clear unmapped buffer\n", __func__); ++ return -EINVAL; ++ } ++ ++ memset(vb->vaddr, 0, vb->size); ++ return vb->size; ++} ++ ++int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset, ++ u8 *data, size_t len) ++{ ++ if (!vb || !vb->vaddr) { ++ dev_err(vpu_dev->dev, "%s: unable to write to unmapped buffer\n", __func__); ++ return -EINVAL; ++ } ++ ++ if (offset > vb->size || len > vb->size || offset + len > vb->size) { ++ dev_err(vpu_dev->dev, "%s: buffer too small\n", __func__); ++ return -ENOSPC; ++ } ++ ++ memcpy(vb->vaddr + offset, data, len); ++ ++ return len; ++} ++ ++int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) ++{ ++ void *vaddr; ++ dma_addr_t daddr; ++ ++ if (!vb->size) { ++ dev_err(vpu_dev->dev, "%s: requested size==0\n", __func__); ++ return -EINVAL; ++ } ++ ++ vaddr = dma_alloc_coherent(vpu_dev->dev, vb->size, &daddr, GFP_KERNEL); ++ if (!vaddr) ++ return -ENOMEM; ++ vb->vaddr = vaddr; ++ vb->daddr = daddr; ++ ++ return 0; ++} ++ ++int wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb) ++{ ++ if (vb->size == 0) ++ return -EINVAL; ++ ++ if (!vb->vaddr) ++ dev_err(vpu_dev->dev, "%s: requested free of unmapped buffer\n", __func__); ++ else ++ dma_free_coherent(vpu_dev->dev, vb->size, vb->vaddr, vb->daddr); ++ ++ memset(vb, 0, sizeof(*vb)); ++ ++ return 0; ++} ++ ++int wave5_vdi_allocate_array(struct vpu_device *vpu_dev, struct vpu_buf *array, unsigned int count, ++ size_t size) ++{ ++ struct vpu_buf vb_buf; ++ int i, ret = 0; ++ ++ vb_buf.size = size; ++ ++ for (i = 0; i < count; i++) { ++ if (array[i].size == size) ++ continue; ++ ++ if (array[i].size != 0) ++ wave5_vdi_free_dma_memory(vpu_dev, &array[i]); ++ ++ ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_buf); ++ if (ret) ++ return -ENOMEM; ++ array[i] = vb_buf; ++ } ++ ++ for (i = count; i < MAX_REG_FRAME; i++) ++ wave5_vdi_free_dma_memory(vpu_dev, &array[i]); ++ ++ return 0; ++} ++ ++void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev) ++{ ++ struct vpu_buf *vb = &vpu_dev->sram_buf; ++ ++ if (!vpu_dev->sram_pool || !vpu_dev->sram_size) ++ return; ++ ++ if (!vb->vaddr) { ++ vb->size = vpu_dev->sram_size; ++ vb->vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, vb->size, ++ &vb->daddr); ++ if (!vb->vaddr) ++ vb->size = 0; ++ } ++ ++ dev_dbg(vpu_dev->dev, "%s: sram daddr: %pad, size: %zu, vaddr: 0x%p\n", ++ __func__, &vb->daddr, vb->size, vb->vaddr); ++} ++ ++void wave5_vdi_free_sram(struct vpu_device *vpu_dev) ++{ ++ struct vpu_buf *vb = &vpu_dev->sram_buf; ++ ++ if (!vb->size || !vb->vaddr) ++ return; ++ ++ if (vb->vaddr) ++ gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr, ++ vb->size); ++ ++ memset(vb, 0, sizeof(*vb)); ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vdi.h b/drivers/media/platform/chips-media/wave5/wave5-vdi.h +--- a/drivers/media/platform/chips-media/wave5/wave5-vdi.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ ++/* ++ * Wave5 series multi-standard codec IP - low level access functions ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#ifndef _VDI_H_ ++#define _VDI_H_ ++ ++#include "wave5-vpuconfig.h" ++#include ++#include ++#include ++ ++/************************************************************************/ ++/* COMMON REGISTERS */ ++/************************************************************************/ ++#define VPU_PRODUCT_CODE_REGISTER 0x1044 ++ ++/* system register write */ ++#define vpu_write_reg(VPU_INST, ADDR, DATA) wave5_vdi_write_register(VPU_INST, ADDR, DATA) ++/* system register read */ ++#define vpu_read_reg(CORE, ADDR) wave5_vdi_read_register(CORE, ADDR) ++ ++struct vpu_buf { ++ size_t size; ++ dma_addr_t daddr; ++ void *vaddr; ++}; ++ ++int wave5_vdi_init(struct device *dev); ++int wave5_vdi_release(struct device *dev); //this function may be called only at system off. ++ ++#endif //#ifndef _VDI_H_ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c +--- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,960 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) ++/* ++ * Wave5 series multi-standard codec IP - helper functions ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#include ++#include "wave5-vpuapi.h" ++#include "wave5-regdefine.h" ++#include "wave5.h" ++ ++#define DECODE_ALL_TEMPORAL_LAYERS 0 ++#define DECODE_ALL_SPATIAL_LAYERS 0 ++ ++static int wave5_initialize_vpu(struct device *dev, u8 *code, size_t size) ++{ ++ int ret; ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ if (wave5_vpu_is_init(vpu_dev)) { ++ wave5_vpu_re_init(dev, (void *)code, size); ++ ret = -EBUSY; ++ goto err_out; ++ } ++ ++ ret = wave5_vpu_reset(dev, SW_RESET_ON_BOOT); ++ if (ret) ++ goto err_out; ++ ++ ret = wave5_vpu_init(dev, (void *)code, size); ++ ++err_out: ++ mutex_unlock(&vpu_dev->hw_lock); ++ return ret; ++} ++ ++int wave5_vpu_init_with_bitcode(struct device *dev, u8 *bitcode, size_t size) ++{ ++ if (!bitcode || size == 0) ++ return -EINVAL; ++ ++ return wave5_initialize_vpu(dev, bitcode, size); ++} ++ ++int wave5_vpu_flush_instance(struct vpu_instance *inst) ++{ ++ int ret = 0; ++ int retry = 0; ++ ++ ret = mutex_lock_interruptible(&inst->dev->hw_lock); ++ if (ret) ++ return ret; ++ do { ++ /* ++ * Repeat the FLUSH command until the firmware reports that the ++ * VPU isn't running anymore ++ */ ++ ret = wave5_vpu_hw_flush_instance(inst); ++ if (ret < 0 && ret != -EBUSY) { ++ dev_warn(inst->dev->dev, "Flush of %s instance with id: %d fail: %d\n", ++ inst->type == VPU_INST_TYPE_DEC ? "DECODER" : "ENCODER", inst->id, ++ ret); ++ mutex_unlock(&inst->dev->hw_lock); ++ return ret; ++ } ++ if (ret == -EBUSY && retry++ >= MAX_FIRMWARE_CALL_RETRY) { ++ dev_warn(inst->dev->dev, "Flush of %s instance with id: %d timed out!\n", ++ inst->type == VPU_INST_TYPE_DEC ? "DECODER" : "ENCODER", inst->id); ++ mutex_unlock(&inst->dev->hw_lock); ++ return -ETIMEDOUT; ++ } ++ } while (ret != 0); ++ mutex_unlock(&inst->dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_get_version_info(struct device *dev, u32 *revision, unsigned int *product_id) ++{ ++ int ret; ++ struct vpu_device *vpu_dev = dev_get_drvdata(dev); ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ if (!wave5_vpu_is_init(vpu_dev)) { ++ ret = -EINVAL; ++ goto err_out; ++ } ++ ++ if (product_id) ++ *product_id = vpu_dev->product; ++ ret = wave5_vpu_get_version(vpu_dev, revision); ++ ++err_out: ++ mutex_unlock(&vpu_dev->hw_lock); ++ return ret; ++} ++ ++static int wave5_check_dec_open_param(struct vpu_instance *inst, struct dec_open_param *param) ++{ ++ if (inst->id >= MAX_NUM_INSTANCE) { ++ dev_err(inst->dev->dev, "Too many simultaneous instances: %d (max: %u)\n", ++ inst->id, MAX_NUM_INSTANCE); ++ return -EOPNOTSUPP; ++ } ++ ++ if (param->bitstream_buffer % 8) { ++ dev_err(inst->dev->dev, ++ "Bitstream buffer must be aligned to a multiple of 8\n"); ++ return -EINVAL; ++ } ++ ++ if (param->bitstream_buffer_size % 1024 || ++ param->bitstream_buffer_size < MIN_BITSTREAM_BUFFER_SIZE) { ++ dev_err(inst->dev->dev, ++ "Bitstream buffer size must be aligned to a multiple of 1024 and have a minimum size of %d\n", ++ MIN_BITSTREAM_BUFFER_SIZE); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++int wave5_vpu_dec_open(struct vpu_instance *inst, struct dec_open_param *open_param) ++{ ++ struct dec_info *p_dec_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ dma_addr_t buffer_addr; ++ size_t buffer_size; ++ ++ ret = wave5_check_dec_open_param(inst, open_param); ++ if (ret) ++ return ret; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ if (!wave5_vpu_is_init(vpu_dev)) { ++ mutex_unlock(&vpu_dev->hw_lock); ++ return -ENODEV; ++ } ++ ++ p_dec_info = &inst->codec_info->dec_info; ++ memcpy(&p_dec_info->open_param, open_param, sizeof(struct dec_open_param)); ++ ++ buffer_addr = open_param->bitstream_buffer; ++ buffer_size = open_param->bitstream_buffer_size; ++ p_dec_info->stream_wr_ptr = buffer_addr; ++ p_dec_info->stream_rd_ptr = buffer_addr; ++ p_dec_info->stream_buf_start_addr = buffer_addr; ++ p_dec_info->stream_buf_size = buffer_size; ++ p_dec_info->stream_buf_end_addr = buffer_addr + buffer_size; ++ p_dec_info->reorder_enable = TRUE; ++ p_dec_info->temp_id_select_mode = TEMPORAL_ID_MODE_ABSOLUTE; ++ p_dec_info->target_temp_id = DECODE_ALL_TEMPORAL_LAYERS; ++ p_dec_info->target_spatial_id = DECODE_ALL_SPATIAL_LAYERS; ++ ++ ret = wave5_vpu_build_up_dec_param(inst, open_param); ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++static int reset_auxiliary_buffers(struct vpu_instance *inst, unsigned int index) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ ++ if (index >= MAX_REG_FRAME) ++ return 1; ++ ++ if (p_dec_info->vb_mv[index].size == 0 && p_dec_info->vb_fbc_y_tbl[index].size == 0 && ++ p_dec_info->vb_fbc_c_tbl[index].size == 0) ++ return 1; ++ ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_mv[index]); ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_y_tbl[index]); ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_c_tbl[index]); ++ ++ return 0; ++} ++ ++int wave5_vpu_dec_close(struct vpu_instance *inst, u32 *fail_res) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret; ++ int retry = 0; ++ struct vpu_device *vpu_dev = inst->dev; ++ int i; ++ ++ *fail_res = 0; ++ if (!inst->codec_info) ++ return -EINVAL; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ do { ++ ret = wave5_vpu_dec_finish_seq(inst, fail_res); ++ if (ret < 0 && *fail_res != WAVE5_SYSERR_VPU_STILL_RUNNING) { ++ dev_warn(inst->dev->dev, "dec_finish_seq timed out\n"); ++ goto unlock_and_return; ++ } ++ ++ if (*fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING && ++ retry++ >= MAX_FIRMWARE_CALL_RETRY) { ++ ret = -ETIMEDOUT; ++ goto unlock_and_return; ++ } ++ } while (ret != 0); ++ ++ dev_dbg(inst->dev->dev, "%s: dec_finish_seq complete\n", __func__); ++ ++ wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_work); ++ ++ for (i = 0 ; i < MAX_REG_FRAME; i++) { ++ ret = reset_auxiliary_buffers(inst, i); ++ if (ret) { ++ ret = 0; ++ break; ++ } ++ } ++ ++ wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_task); ++ ++unlock_and_return: ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_issue_seq_init(struct vpu_instance *inst) ++{ ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ ret = wave5_vpu_dec_init_seq(inst); ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_complete_seq_init(struct vpu_instance *inst, struct dec_initial_info *info) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ ret = wave5_vpu_dec_get_seq_info(inst, info); ++ if (!ret) ++ p_dec_info->initial_info_obtained = true; ++ ++ info->rd_ptr = wave5_dec_get_rd_ptr(inst); ++ info->wr_ptr = p_dec_info->stream_wr_ptr; ++ ++ p_dec_info->initial_info = *info; ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_register_frame_buffer_ex(struct vpu_instance *inst, int num_of_decoding_fbs, ++ int num_of_display_fbs, int stride, int height) ++{ ++ struct dec_info *p_dec_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ struct frame_buffer *fb; ++ ++ if (num_of_decoding_fbs >= WAVE5_MAX_FBS || num_of_display_fbs >= WAVE5_MAX_FBS) ++ return -EINVAL; ++ ++ p_dec_info = &inst->codec_info->dec_info; ++ p_dec_info->num_of_decoding_fbs = num_of_decoding_fbs; ++ p_dec_info->num_of_display_fbs = num_of_display_fbs; ++ p_dec_info->stride = stride; ++ ++ if (!p_dec_info->initial_info_obtained) ++ return -EINVAL; ++ ++ if (stride < p_dec_info->initial_info.pic_width || (stride % 8 != 0) || ++ height < p_dec_info->initial_info.pic_height) ++ return -EINVAL; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ fb = inst->frame_buf; ++ ret = wave5_vpu_dec_register_framebuffer(inst, &fb[p_dec_info->num_of_decoding_fbs], ++ LINEAR_FRAME_MAP, p_dec_info->num_of_display_fbs); ++ if (ret) ++ goto err_out; ++ ++ ret = wave5_vpu_dec_register_framebuffer(inst, &fb[0], COMPRESSED_FRAME_MAP, ++ p_dec_info->num_of_decoding_fbs); ++ ++err_out: ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_get_bitstream_buffer(struct vpu_instance *inst, dma_addr_t *prd_ptr, ++ dma_addr_t *pwr_ptr, size_t *size) ++{ ++ struct dec_info *p_dec_info; ++ dma_addr_t rd_ptr; ++ dma_addr_t wr_ptr; ++ int room; ++ struct vpu_device *vpu_dev = inst->dev; ++ int ret; ++ ++ p_dec_info = &inst->codec_info->dec_info; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ rd_ptr = wave5_dec_get_rd_ptr(inst); ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ wr_ptr = p_dec_info->stream_wr_ptr; ++ ++ if (wr_ptr < rd_ptr) ++ room = rd_ptr - wr_ptr; ++ else ++ room = (p_dec_info->stream_buf_end_addr - wr_ptr) + ++ (rd_ptr - p_dec_info->stream_buf_start_addr); ++ room--; ++ ++ if (prd_ptr) ++ *prd_ptr = rd_ptr; ++ if (pwr_ptr) ++ *pwr_ptr = wr_ptr; ++ if (size) ++ *size = room; ++ ++ return 0; ++} ++ ++int wave5_vpu_dec_update_bitstream_buffer(struct vpu_instance *inst, size_t size) ++{ ++ struct dec_info *p_dec_info; ++ dma_addr_t wr_ptr; ++ dma_addr_t rd_ptr; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ if (!inst->codec_info) ++ return -EINVAL; ++ ++ p_dec_info = &inst->codec_info->dec_info; ++ wr_ptr = p_dec_info->stream_wr_ptr; ++ rd_ptr = p_dec_info->stream_rd_ptr; ++ ++ if (size > 0) { ++ if (wr_ptr < rd_ptr && rd_ptr <= wr_ptr + size) ++ return -EINVAL; ++ ++ wr_ptr += size; ++ ++ if (wr_ptr > p_dec_info->stream_buf_end_addr) { ++ u32 room = wr_ptr - p_dec_info->stream_buf_end_addr; ++ ++ wr_ptr = p_dec_info->stream_buf_start_addr; ++ wr_ptr += room; ++ } else if (wr_ptr == p_dec_info->stream_buf_end_addr) { ++ wr_ptr = p_dec_info->stream_buf_start_addr; ++ } ++ ++ p_dec_info->stream_wr_ptr = wr_ptr; ++ p_dec_info->stream_rd_ptr = rd_ptr; ++ } ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ret = wave5_vpu_dec_set_bitstream_flag(inst, (size == 0)); ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_start_one_frame(struct vpu_instance *inst, u32 *res_fail) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ if (p_dec_info->stride == 0) /* this means frame buffers have not been registered. */ ++ return -EINVAL; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ ret = wave5_vpu_decode(inst, res_fail); ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr, int update_wr_ptr) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ ret = wave5_dec_set_rd_ptr(inst, addr); ++ ++ p_dec_info->stream_rd_ptr = addr; ++ if (update_wr_ptr) ++ p_dec_info->stream_wr_ptr = addr; ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++dma_addr_t wave5_vpu_dec_get_rd_ptr(struct vpu_instance *inst) ++{ ++ int ret; ++ dma_addr_t rd_ptr; ++ ++ ret = mutex_lock_interruptible(&inst->dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ rd_ptr = wave5_dec_get_rd_ptr(inst); ++ ++ mutex_unlock(&inst->dev->hw_lock); ++ ++ return rd_ptr; ++} ++ ++int wave5_vpu_dec_get_output_info(struct vpu_instance *inst, struct dec_output_info *info) ++{ ++ struct dec_info *p_dec_info; ++ int ret; ++ struct vpu_rect rect_info; ++ u32 val; ++ u32 decoded_index; ++ u32 disp_idx; ++ u32 max_dec_index; ++ struct vpu_device *vpu_dev = inst->dev; ++ struct dec_output_info *disp_info; ++ ++ if (!info) ++ return -EINVAL; ++ ++ p_dec_info = &inst->codec_info->dec_info; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ memset(info, 0, sizeof(*info)); ++ ++ ret = wave5_vpu_dec_get_result(inst, info); ++ if (ret) { ++ info->rd_ptr = p_dec_info->stream_rd_ptr; ++ info->wr_ptr = p_dec_info->stream_wr_ptr; ++ goto err_out; ++ } ++ ++ decoded_index = info->index_frame_decoded; ++ ++ /* calculate display frame region */ ++ val = 0; ++ rect_info.left = 0; ++ rect_info.right = 0; ++ rect_info.top = 0; ++ rect_info.bottom = 0; ++ ++ if (decoded_index < WAVE5_MAX_FBS) { ++ if (inst->std == W_HEVC_DEC || inst->std == W_AVC_DEC) ++ rect_info = p_dec_info->initial_info.pic_crop_rect; ++ ++ if (inst->std == W_HEVC_DEC) ++ p_dec_info->dec_out_info[decoded_index].decoded_poc = info->decoded_poc; ++ ++ p_dec_info->dec_out_info[decoded_index].rc_decoded = rect_info; ++ } ++ info->rc_decoded = rect_info; ++ ++ disp_idx = info->index_frame_display; ++ disp_info = &p_dec_info->dec_out_info[disp_idx]; ++ if (info->index_frame_display >= 0 && info->index_frame_display < WAVE5_MAX_FBS) { ++ if (info->index_frame_display != info->index_frame_decoded) { ++ /* ++ * when index_frame_decoded < 0, and index_frame_display >= 0 ++ * info->dec_pic_width and info->dec_pic_height are still valid ++ * but those of p_dec_info->dec_out_info[disp_idx] are invalid in VP9 ++ */ ++ info->disp_pic_width = disp_info->dec_pic_width; ++ info->disp_pic_height = disp_info->dec_pic_height; ++ } else { ++ info->disp_pic_width = info->dec_pic_width; ++ info->disp_pic_height = info->dec_pic_height; ++ } ++ ++ info->rc_display = disp_info->rc_decoded; ++ ++ } else { ++ info->rc_display.left = 0; ++ info->rc_display.right = 0; ++ info->rc_display.top = 0; ++ info->rc_display.bottom = 0; ++ info->disp_pic_width = 0; ++ info->disp_pic_height = 0; ++ } ++ ++ p_dec_info->stream_rd_ptr = wave5_dec_get_rd_ptr(inst); ++ p_dec_info->frame_display_flag = vpu_read_reg(vpu_dev, W5_RET_DEC_DISP_IDC); ++ ++ val = p_dec_info->num_of_decoding_fbs; //fb_offset ++ ++ max_dec_index = (p_dec_info->num_of_decoding_fbs > p_dec_info->num_of_display_fbs) ? ++ p_dec_info->num_of_decoding_fbs : p_dec_info->num_of_display_fbs; ++ ++ if (info->index_frame_display >= 0 && ++ info->index_frame_display < (int)max_dec_index) ++ info->disp_frame = inst->frame_buf[val + info->index_frame_display]; ++ ++ info->rd_ptr = p_dec_info->stream_rd_ptr; ++ info->wr_ptr = p_dec_info->stream_wr_ptr; ++ info->frame_display_flag = p_dec_info->frame_display_flag; ++ ++ info->sequence_no = p_dec_info->initial_info.sequence_no; ++ if (decoded_index < WAVE5_MAX_FBS) ++ p_dec_info->dec_out_info[decoded_index] = *info; ++ ++ if (disp_idx < WAVE5_MAX_FBS) ++ info->disp_frame.sequence_no = info->sequence_no; ++ ++ if (info->sequence_changed) { ++ memcpy((void *)&p_dec_info->initial_info, (void *)&p_dec_info->new_seq_info, ++ sizeof(struct dec_initial_info)); ++ p_dec_info->initial_info.sequence_no++; ++ } ++ ++err_out: ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_clr_disp_flag(struct vpu_instance *inst, int index) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ if (index >= p_dec_info->num_of_display_fbs) ++ return -EINVAL; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ret = wave5_dec_clr_disp_flag(inst, index); ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_set_disp_flag(struct vpu_instance *inst, int index) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret = 0; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ if (index >= p_dec_info->num_of_display_fbs) ++ return -EINVAL; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ret = wave5_dec_set_disp_flag(inst, index); ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_dec_reset_framebuffer(struct vpu_instance *inst, unsigned int index) ++{ ++ if (index >= MAX_REG_FRAME) ++ return -EINVAL; ++ ++ if (inst->frame_vbuf[index].size == 0) ++ return -EINVAL; ++ ++ wave5_vdi_free_dma_memory(inst->dev, &inst->frame_vbuf[index]); ++ ++ return 0; ++} ++ ++int wave5_vpu_dec_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter) ++{ ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ int ret = 0; ++ ++ switch (cmd) { ++ case DEC_GET_QUEUE_STATUS: { ++ struct queue_status_info *queue_info = parameter; ++ ++ queue_info->instance_queue_count = p_dec_info->instance_queue_count; ++ queue_info->report_queue_count = p_dec_info->report_queue_count; ++ break; ++ } ++ case DEC_RESET_FRAMEBUF_INFO: { ++ int i; ++ ++ for (i = 0; i < MAX_REG_FRAME; i++) { ++ ret = wave5_vpu_dec_reset_framebuffer(inst, i); ++ if (ret) ++ break; ++ } ++ ++ for (i = 0; i < MAX_REG_FRAME; i++) { ++ ret = reset_auxiliary_buffers(inst, i); ++ if (ret) ++ break; ++ } ++ ++ wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task); ++ break; ++ } ++ case DEC_GET_SEQ_INFO: { ++ struct dec_initial_info *seq_info = parameter; ++ ++ *seq_info = p_dec_info->initial_info; ++ break; ++ } ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++ ++int wave5_vpu_enc_open(struct vpu_instance *inst, struct enc_open_param *open_param) ++{ ++ struct enc_info *p_enc_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ ret = wave5_vpu_enc_check_open_param(inst, open_param); ++ if (ret) ++ return ret; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ if (!wave5_vpu_is_init(vpu_dev)) { ++ mutex_unlock(&vpu_dev->hw_lock); ++ return -ENODEV; ++ } ++ ++ p_enc_info = &inst->codec_info->enc_info; ++ p_enc_info->open_param = *open_param; ++ ++ ret = wave5_vpu_build_up_enc_param(vpu_dev->dev, inst, open_param); ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_enc_close(struct vpu_instance *inst, u32 *fail_res) ++{ ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ int ret; ++ int retry = 0; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ *fail_res = 0; ++ if (!inst->codec_info) ++ return -EINVAL; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ do { ++ ret = wave5_vpu_enc_finish_seq(inst, fail_res); ++ if (ret < 0 && *fail_res != WAVE5_SYSERR_VPU_STILL_RUNNING) { ++ dev_warn(inst->dev->dev, "enc_finish_seq timed out\n"); ++ mutex_unlock(&vpu_dev->hw_lock); ++ return ret; ++ } ++ ++ if (*fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING && ++ retry++ >= MAX_FIRMWARE_CALL_RETRY) { ++ mutex_unlock(&vpu_dev->hw_lock); ++ return -ETIMEDOUT; ++ } ++ } while (ret != 0); ++ ++ dev_dbg(inst->dev->dev, "%s: enc_finish_seq complete\n", __func__); ++ ++ wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_work); ++ ++ if (inst->std == W_HEVC_ENC || inst->std == W_AVC_ENC) { ++ wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_sub_sam_buf); ++ wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_mv); ++ wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_fbc_y_tbl); ++ wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_fbc_c_tbl); ++ } ++ ++ wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_task); ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return 0; ++} ++ ++int wave5_vpu_enc_register_frame_buffer(struct vpu_instance *inst, unsigned int num, ++ unsigned int stride, int height, ++ enum tiled_map_type map_type) ++{ ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ unsigned int size_luma, size_chroma; ++ int i; ++ ++ if (p_enc_info->stride) ++ return -EINVAL; ++ ++ if (!p_enc_info->initial_info_obtained) ++ return -EINVAL; ++ ++ if (num < p_enc_info->initial_info.min_frame_buffer_count) ++ return -EINVAL; ++ ++ if (stride == 0 || stride % 8 != 0) ++ return -EINVAL; ++ ++ if (height <= 0) ++ return -EINVAL; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ p_enc_info->num_frame_buffers = num; ++ p_enc_info->stride = stride; ++ ++ size_luma = stride * height; ++ size_chroma = ALIGN(stride / 2, 16) * height; ++ ++ for (i = 0; i < num; i++) { ++ if (!inst->frame_buf[i].update_fb_info) ++ continue; ++ ++ inst->frame_buf[i].update_fb_info = false; ++ inst->frame_buf[i].stride = stride; ++ inst->frame_buf[i].height = height; ++ inst->frame_buf[i].map_type = COMPRESSED_FRAME_MAP; ++ inst->frame_buf[i].buf_y_size = size_luma; ++ inst->frame_buf[i].buf_cb = inst->frame_buf[i].buf_y + size_luma; ++ inst->frame_buf[i].buf_cb_size = size_chroma; ++ inst->frame_buf[i].buf_cr_size = 0; ++ } ++ ++ ret = wave5_vpu_enc_register_framebuffer(inst->dev->dev, inst, &inst->frame_buf[0], ++ COMPRESSED_FRAME_MAP, ++ p_enc_info->num_frame_buffers); ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++static int wave5_check_enc_param(struct vpu_instance *inst, struct enc_param *param) ++{ ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ ++ if (!param) ++ return -EINVAL; ++ ++ if (!param->source_frame) ++ return -EINVAL; ++ ++ if (p_enc_info->open_param.bit_rate == 0 && inst->std == W_HEVC_ENC) { ++ if (param->pic_stream_buffer_addr % 16 || param->pic_stream_buffer_size == 0) ++ return -EINVAL; ++ } ++ if (param->pic_stream_buffer_addr % 8 || param->pic_stream_buffer_size == 0) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++int wave5_vpu_enc_start_one_frame(struct vpu_instance *inst, struct enc_param *param, u32 *fail_res) ++{ ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ *fail_res = 0; ++ ++ if (p_enc_info->stride == 0) /* this means frame buffers have not been registered. */ ++ return -EINVAL; ++ ++ ret = wave5_check_enc_param(inst, param); ++ if (ret) ++ return ret; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ p_enc_info->pts_map[param->src_idx] = param->pts; ++ ++ ret = wave5_vpu_encode(inst, param, fail_res); ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_enc_get_output_info(struct vpu_instance *inst, struct enc_output_info *info) ++{ ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ ret = wave5_vpu_enc_get_result(inst, info); ++ if (ret) { ++ info->pts = 0; ++ goto unlock; ++ } ++ ++ if (info->recon_frame_index >= 0) ++ info->pts = p_enc_info->pts_map[info->enc_src_idx]; ++ ++unlock: ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_enc_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter) ++{ ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ ++ switch (cmd) { ++ case ENABLE_ROTATION: ++ p_enc_info->rotation_enable = true; ++ break; ++ case ENABLE_MIRRORING: ++ p_enc_info->mirror_enable = true; ++ break; ++ case SET_MIRROR_DIRECTION: { ++ enum mirror_direction mir_dir; ++ ++ mir_dir = *(enum mirror_direction *)parameter; ++ if (mir_dir != MIRDIR_NONE && mir_dir != MIRDIR_HOR && ++ mir_dir != MIRDIR_VER && mir_dir != MIRDIR_HOR_VER) ++ return -EINVAL; ++ p_enc_info->mirror_direction = mir_dir; ++ break; ++ } ++ case SET_ROTATION_ANGLE: { ++ int angle; ++ ++ angle = *(int *)parameter; ++ if (angle && angle != 90 && angle != 180 && angle != 270) ++ return -EINVAL; ++ if (p_enc_info->initial_info_obtained && (angle == 90 || angle == 270)) ++ return -EINVAL; ++ p_enc_info->rotation_angle = angle; ++ break; ++ } ++ case ENC_GET_QUEUE_STATUS: { ++ struct queue_status_info *queue_info = parameter; ++ ++ queue_info->instance_queue_count = p_enc_info->instance_queue_count; ++ queue_info->report_queue_count = p_enc_info->report_queue_count; ++ break; ++ } ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++int wave5_vpu_enc_issue_seq_init(struct vpu_instance *inst) ++{ ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ ret = wave5_vpu_enc_init_seq(inst); ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return ret; ++} ++ ++int wave5_vpu_enc_complete_seq_init(struct vpu_instance *inst, struct enc_initial_info *info) ++{ ++ struct enc_info *p_enc_info = &inst->codec_info->enc_info; ++ int ret; ++ struct vpu_device *vpu_dev = inst->dev; ++ ++ if (!info) ++ return -EINVAL; ++ ++ ret = mutex_lock_interruptible(&vpu_dev->hw_lock); ++ if (ret) ++ return ret; ++ ++ ret = wave5_vpu_enc_get_seq_info(inst, info); ++ if (ret) { ++ p_enc_info->initial_info_obtained = false; ++ mutex_unlock(&vpu_dev->hw_lock); ++ return ret; ++ } ++ ++ p_enc_info->initial_info_obtained = true; ++ p_enc_info->initial_info = *info; ++ ++ mutex_unlock(&vpu_dev->hw_lock); ++ ++ return 0; ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h +--- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,870 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ ++/* ++ * Wave5 series multi-standard codec IP - helper definitions ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#ifndef VPUAPI_H_INCLUDED ++#define VPUAPI_H_INCLUDED ++ ++#include ++#include ++#include ++#include ++#include ++#include "wave5-vpuerror.h" ++#include "wave5-vpuconfig.h" ++#include "wave5-vdi.h" ++ ++enum product_id { ++ PRODUCT_ID_521, ++ PRODUCT_ID_511, ++ PRODUCT_ID_517, ++ PRODUCT_ID_NONE, ++}; ++ ++struct vpu_attr; ++ ++enum vpu_instance_type { ++ VPU_INST_TYPE_DEC = 0, ++ VPU_INST_TYPE_ENC = 1 ++}; ++ ++enum vpu_instance_state { ++ VPU_INST_STATE_NONE = 0, ++ VPU_INST_STATE_OPEN = 1, ++ VPU_INST_STATE_INIT_SEQ = 2, ++ VPU_INST_STATE_PIC_RUN = 3, ++ VPU_INST_STATE_STOP = 4 ++}; ++ ++/* Maximum available on hardware. */ ++#define WAVE5_MAX_FBS 32 ++ ++#define MAX_REG_FRAME (WAVE5_MAX_FBS * 2) ++ ++#define WAVE5_DEC_HEVC_BUF_SIZE(_w, _h) (DIV_ROUND_UP(_w, 64) * DIV_ROUND_UP(_h, 64) * 256 + 64) ++#define WAVE5_DEC_AVC_BUF_SIZE(_w, _h) ((((ALIGN(_w, 256) / 16) * (ALIGN(_h, 16) / 16)) + 16) * 80) ++ ++#define WAVE5_FBC_LUMA_TABLE_SIZE(_w, _h) (ALIGN(_h, 64) * ALIGN(_w, 256) / 32) ++#define WAVE5_FBC_CHROMA_TABLE_SIZE(_w, _h) (ALIGN((_h), 64) * ALIGN((_w) / 2, 256) / 32) ++#define WAVE5_ENC_AVC_BUF_SIZE(_w, _h) (ALIGN(_w, 64) * ALIGN(_h, 64) / 32) ++#define WAVE5_ENC_HEVC_BUF_SIZE(_w, _h) (ALIGN(_w, 64) / 64 * ALIGN(_h, 64) / 64 * 128) ++ ++/* ++ * common struct and definition ++ */ ++enum cod_std { ++ STD_AVC = 0, ++ STD_HEVC = 12, ++ STD_MAX ++}; ++ ++enum wave_std { ++ W_HEVC_DEC = 0x00, ++ W_HEVC_ENC = 0x01, ++ W_AVC_DEC = 0x02, ++ W_AVC_ENC = 0x03, ++ STD_UNKNOWN = 0xFF ++}; ++ ++enum set_param_option { ++ OPT_COMMON = 0, /* SET_PARAM command option for encoding sequence */ ++ OPT_CUSTOM_GOP = 1, /* SET_PARAM command option for setting custom GOP */ ++ OPT_CUSTOM_HEADER = 2, /* SET_PARAM command option for setting custom VPS/SPS/PPS */ ++ OPT_VUI = 3, /* SET_PARAM command option for encoding VUI */ ++ OPT_CHANGE_PARAM = 0x10, ++}; ++ ++/************************************************************************/ ++/* PROFILE & LEVEL */ ++/************************************************************************/ ++/* HEVC */ ++#define HEVC_PROFILE_MAIN 1 ++#define HEVC_PROFILE_MAIN10 2 ++#define HEVC_PROFILE_STILLPICTURE 3 ++#define HEVC_PROFILE_MAIN10_STILLPICTURE 2 ++ ++/* H.264 profile for encoder*/ ++#define H264_PROFILE_BP 1 ++#define H264_PROFILE_MP 2 ++#define H264_PROFILE_EXTENDED 3 ++#define H264_PROFILE_HP 4 ++#define H264_PROFILE_HIGH10 5 ++#define H264_PROFILE_HIGH422 6 ++#define H264_PROFILE_HIGH444 7 ++ ++/************************************************************************/ ++/* error codes */ ++/************************************************************************/ ++ ++/************************************************************************/ ++/* utility macros */ ++/************************************************************************/ ++ ++/* Initialize sequence firmware command mode */ ++#define INIT_SEQ_NORMAL 1 ++ ++/* Decode firmware command mode */ ++#define DEC_PIC_NORMAL 0 ++ ++/* bit_alloc_mode */ ++#define BIT_ALLOC_MODE_FIXED_RATIO 2 ++ ++/* bit_rate */ ++#define MAX_BIT_RATE 700000000 ++ ++/* decoding_refresh_type */ ++#define DEC_REFRESH_TYPE_NON_IRAP 0 ++#define DEC_REFRESH_TYPE_CRA 1 ++#define DEC_REFRESH_TYPE_IDR 2 ++ ++/* depend_slice_mode */ ++#define DEPEND_SLICE_MODE_RECOMMENDED 1 ++#define DEPEND_SLICE_MODE_BOOST 2 ++#define DEPEND_SLICE_MODE_FAST 3 ++ ++/* hvs_max_delta_qp */ ++#define MAX_HVS_MAX_DELTA_QP 51 ++ ++/* intra_refresh_mode */ ++#define REFRESH_MODE_CTU_ROWS 1 ++#define REFRESH_MODE_CTU_COLUMNS 2 ++#define REFRESH_MODE_CTU_STEP_SIZE 3 ++#define REFRESH_MODE_CTUS 4 ++ ++/* intra_mb_refresh_mode */ ++#define REFRESH_MB_MODE_NONE 0 ++#define REFRESH_MB_MODE_CTU_ROWS 1 ++#define REFRESH_MB_MODE_CTU_COLUMNS 2 ++#define REFRESH_MB_MODE_CTU_STEP_SIZE 3 ++ ++/* intra_qp */ ++#define MAX_INTRA_QP 63 ++ ++/* nr_inter_weight_* */ ++#define MAX_INTER_WEIGHT 31 ++ ++/* nr_intra_weight_* */ ++#define MAX_INTRA_WEIGHT 31 ++ ++/* nr_noise_sigma_* */ ++#define MAX_NOISE_SIGMA 255 ++ ++/* bitstream_buffer_size */ ++#define MIN_BITSTREAM_BUFFER_SIZE 1024 ++#define MIN_BITSTREAM_BUFFER_SIZE_WAVE521 (1024 * 64) ++ ++/* vbv_buffer_size */ ++#define MIN_VBV_BUFFER_SIZE 10 ++#define MAX_VBV_BUFFER_SIZE 3000 ++ ++#define BUFFER_MARGIN 4096 ++ ++#define MAX_FIRMWARE_CALL_RETRY 10 ++ ++#define VDI_LITTLE_ENDIAN 0x0 ++ ++/* ++ * Parameters of DEC_SET_SEQ_CHANGE_MASK ++ */ ++#define SEQ_CHANGE_ENABLE_PROFILE BIT(5) ++#define SEQ_CHANGE_ENABLE_SIZE BIT(16) ++#define SEQ_CHANGE_ENABLE_BITDEPTH BIT(18) ++#define SEQ_CHANGE_ENABLE_DPB_COUNT BIT(19) ++#define SEQ_CHANGE_ENABLE_ASPECT_RATIO BIT(21) ++#define SEQ_CHANGE_ENABLE_VIDEO_SIGNAL BIT(23) ++#define SEQ_CHANGE_ENABLE_VUI_TIMING_INFO BIT(29) ++ ++#define SEQ_CHANGE_ENABLE_ALL_HEVC (SEQ_CHANGE_ENABLE_PROFILE | \ ++ SEQ_CHANGE_ENABLE_SIZE | \ ++ SEQ_CHANGE_ENABLE_BITDEPTH | \ ++ SEQ_CHANGE_ENABLE_DPB_COUNT) ++ ++#define SEQ_CHANGE_ENABLE_ALL_AVC (SEQ_CHANGE_ENABLE_SIZE | \ ++ SEQ_CHANGE_ENABLE_BITDEPTH | \ ++ SEQ_CHANGE_ENABLE_DPB_COUNT | \ ++ SEQ_CHANGE_ENABLE_ASPECT_RATIO | \ ++ SEQ_CHANGE_ENABLE_VIDEO_SIGNAL | \ ++ SEQ_CHANGE_ENABLE_VUI_TIMING_INFO) ++ ++#define DISPLAY_IDX_FLAG_SEQ_END -1 ++#define DISPLAY_IDX_FLAG_NO_FB -3 ++#define DECODED_IDX_FLAG_NO_FB -1 ++#define DECODED_IDX_FLAG_SKIP -2 ++ ++#define RECON_IDX_FLAG_ENC_END -1 ++#define RECON_IDX_FLAG_ENC_DELAY -2 ++#define RECON_IDX_FLAG_HEADER_ONLY -3 ++#define RECON_IDX_FLAG_CHANGE_PARAM -4 ++ ++enum codec_command { ++ ENABLE_ROTATION, ++ ENABLE_MIRRORING, ++ SET_MIRROR_DIRECTION, ++ SET_ROTATION_ANGLE, ++ DEC_GET_QUEUE_STATUS, ++ ENC_GET_QUEUE_STATUS, ++ DEC_RESET_FRAMEBUF_INFO, ++ DEC_GET_SEQ_INFO, ++}; ++ ++enum mirror_direction { ++ MIRDIR_NONE, /* no mirroring */ ++ MIRDIR_VER, /* vertical mirroring */ ++ MIRDIR_HOR, /* horizontal mirroring */ ++ MIRDIR_HOR_VER /* horizontal and vertical mirroring */ ++}; ++ ++enum frame_buffer_format { ++ FORMAT_ERR = -1, ++ FORMAT_420 = 0, /* 8bit */ ++ FORMAT_422, /* 8bit */ ++ FORMAT_224, /* 8bit */ ++ FORMAT_444, /* 8bit */ ++ FORMAT_400, /* 8bit */ ++ ++ /* little endian perspective */ ++ /* | addr 0 | addr 1 | */ ++ FORMAT_420_P10_16BIT_MSB = 5, /* lsb |000000xx|xxxxxxxx | msb */ ++ FORMAT_420_P10_16BIT_LSB, /* lsb |xxxxxxx |xx000000 | msb */ ++ FORMAT_420_P10_32BIT_MSB, /* lsb |00xxxxxxxxxxxxxxxxxxxxxxxxxxx| msb */ ++ FORMAT_420_P10_32BIT_LSB, /* lsb |xxxxxxxxxxxxxxxxxxxxxxxxxxx00| msb */ ++ ++ /* 4:2:2 packed format */ ++ /* little endian perspective */ ++ /* | addr 0 | addr 1 | */ ++ FORMAT_422_P10_16BIT_MSB, /* lsb |000000xx |xxxxxxxx | msb */ ++ FORMAT_422_P10_16BIT_LSB, /* lsb |xxxxxxxx |xx000000 | msb */ ++ FORMAT_422_P10_32BIT_MSB, /* lsb |00xxxxxxxxxxxxxxxxxxxxxxxxxxx| msb */ ++ FORMAT_422_P10_32BIT_LSB, /* lsb |xxxxxxxxxxxxxxxxxxxxxxxxxxx00| msb */ ++ ++ FORMAT_YUYV, /* 8bit packed format : Y0U0Y1V0 Y2U1Y3V1 ... */ ++ FORMAT_YUYV_P10_16BIT_MSB, ++ FORMAT_YUYV_P10_16BIT_LSB, ++ FORMAT_YUYV_P10_32BIT_MSB, ++ FORMAT_YUYV_P10_32BIT_LSB, ++ ++ FORMAT_YVYU, /* 8bit packed format : Y0V0Y1U0 Y2V1Y3U1 ... */ ++ FORMAT_YVYU_P10_16BIT_MSB, ++ FORMAT_YVYU_P10_16BIT_LSB, ++ FORMAT_YVYU_P10_32BIT_MSB, ++ FORMAT_YVYU_P10_32BIT_LSB, ++ ++ FORMAT_UYVY, /* 8bit packed format : U0Y0V0Y1 U1Y2V1Y3 ... */ ++ FORMAT_UYVY_P10_16BIT_MSB, ++ FORMAT_UYVY_P10_16BIT_LSB, ++ FORMAT_UYVY_P10_32BIT_MSB, ++ FORMAT_UYVY_P10_32BIT_LSB, ++ ++ FORMAT_VYUY, /* 8bit packed format : V0Y0U0Y1 V1Y2U1Y3 ... */ ++ FORMAT_VYUY_P10_16BIT_MSB, ++ FORMAT_VYUY_P10_16BIT_LSB, ++ FORMAT_VYUY_P10_32BIT_MSB, ++ FORMAT_VYUY_P10_32BIT_LSB, ++ ++ FORMAT_MAX, ++}; ++ ++enum packed_format_num { ++ NOT_PACKED = 0, ++ PACKED_YUYV, ++ PACKED_YVYU, ++ PACKED_UYVY, ++ PACKED_VYUY, ++}; ++ ++enum wave5_interrupt_bit { ++ INT_WAVE5_INIT_VPU = 0, ++ INT_WAVE5_WAKEUP_VPU = 1, ++ INT_WAVE5_SLEEP_VPU = 2, ++ INT_WAVE5_CREATE_INSTANCE = 3, ++ INT_WAVE5_FLUSH_INSTANCE = 4, ++ INT_WAVE5_DESTROY_INSTANCE = 5, ++ INT_WAVE5_INIT_SEQ = 6, ++ INT_WAVE5_SET_FRAMEBUF = 7, ++ INT_WAVE5_DEC_PIC = 8, ++ INT_WAVE5_ENC_PIC = 8, ++ INT_WAVE5_ENC_SET_PARAM = 9, ++ INT_WAVE5_DEC_QUERY = 14, ++ INT_WAVE5_BSBUF_EMPTY = 15, ++ INT_WAVE5_BSBUF_FULL = 15, ++}; ++ ++enum pic_type { ++ PIC_TYPE_I = 0, ++ PIC_TYPE_P = 1, ++ PIC_TYPE_B = 2, ++ PIC_TYPE_IDR = 5, /* H.264/H.265 IDR (Instantaneous Decoder Refresh) picture */ ++ PIC_TYPE_MAX /* no meaning */ ++}; ++ ++enum sw_reset_mode { ++ SW_RESET_SAFETY, ++ SW_RESET_FORCE, ++ SW_RESET_ON_BOOT ++}; ++ ++enum tiled_map_type { ++ LINEAR_FRAME_MAP = 0, /* linear frame map type */ ++ COMPRESSED_FRAME_MAP = 17, /* compressed frame map type*/ ++}; ++ ++enum temporal_id_mode { ++ TEMPORAL_ID_MODE_ABSOLUTE, ++ TEMPORAL_ID_MODE_RELATIVE, ++}; ++ ++struct vpu_attr { ++ u32 product_id; ++ char product_name[8]; /* product name in ascii code */ ++ u32 product_version; ++ u32 fw_version; ++ u32 customer_id; ++ u32 support_decoders; /* bitmask */ ++ u32 support_encoders; /* bitmask */ ++ u32 support_backbone: 1; ++ u32 support_avc10bit_enc: 1; ++ u32 support_hevc10bit_enc: 1; ++ u32 support_vcore_backbone: 1; ++ u32 support_vcpu_backbone: 1; ++}; ++ ++struct frame_buffer { ++ dma_addr_t buf_y; ++ dma_addr_t buf_cb; ++ dma_addr_t buf_cr; ++ unsigned int buf_y_size; ++ unsigned int buf_cb_size; ++ unsigned int buf_cr_size; ++ enum tiled_map_type map_type; ++ unsigned int stride; /* horizontal stride for the given frame buffer */ ++ unsigned int width; /* width of the given frame buffer */ ++ unsigned int height; /* height of the given frame buffer */ ++ size_t size; /* size of the given frame buffer */ ++ unsigned int sequence_no; ++ bool update_fb_info; ++}; ++ ++struct vpu_rect { ++ unsigned int left; /* horizontal pixel offset from left edge */ ++ unsigned int top; /* vertical pixel offset from top edge */ ++ unsigned int right; /* horizontal pixel offset from right edge */ ++ unsigned int bottom; /* vertical pixel offset from bottom edge */ ++}; ++ ++/* ++ * decode struct and definition ++ */ ++ ++struct dec_open_param { ++ dma_addr_t bitstream_buffer; ++ size_t bitstream_buffer_size; ++}; ++ ++struct dec_initial_info { ++ u32 pic_width; ++ u32 pic_height; ++ struct vpu_rect pic_crop_rect; ++ u32 min_frame_buffer_count; /* between 1 to 16 */ ++ ++ u32 profile; ++ u32 luma_bitdepth; /* bit-depth of the luma sample */ ++ u32 chroma_bitdepth; /* bit-depth of the chroma sample */ ++ u32 seq_init_err_reason; ++ dma_addr_t rd_ptr; /* read pointer of bitstream buffer */ ++ dma_addr_t wr_ptr; /* write pointer of bitstream buffer */ ++ u32 sequence_no; ++ u32 vlc_buf_size; ++ u32 param_buf_size; ++}; ++ ++struct dec_output_info { ++ /** ++ * This is a frame buffer index for the picture to be displayed at the moment ++ * among frame buffers which are registered using vpu_dec_register_frame_buffer(). ++ * Frame data that will be displayed is stored in the frame buffer with this index ++ * When there is no display delay, this index is always the equal to ++ * index_frame_decoded, however, if displaying is delayed (for display ++ * reordering in AVC or B-frames in VC1), this index might be different to ++ * index_frame_decoded. By checking this index, HOST applications can easily figure ++ * out whether sequence decoding has been finished or not. ++ * ++ * -3(0xFFFD) or -2(0xFFFE) : when a display output cannot be given due to picture ++ * reordering or skip option ++ * -1(0xFFFF) : when there is no more output for display at the end of sequence ++ * decoding ++ */ ++ s32 index_frame_display; ++ /** ++ * This is the frame buffer index of the decoded picture among the frame buffers which were ++ * registered using vpu_dec_register_frame_buffer(). The currently decoded frame is stored ++ * into the frame buffer specified by this index. ++ * ++ * -2 : indicates that no decoded output is generated because decoder meets EOS ++ * (end of sequence) or skip ++ * -1 : indicates that the decoder fails to decode a picture because there is no available ++ * frame buffer ++ */ ++ s32 index_frame_decoded; ++ s32 index_frame_decoded_for_tiled; ++ u32 nal_type; ++ unsigned int pic_type; ++ struct vpu_rect rc_display; ++ unsigned int disp_pic_width; ++ unsigned int disp_pic_height; ++ struct vpu_rect rc_decoded; ++ u32 dec_pic_width; ++ u32 dec_pic_height; ++ s32 decoded_poc; ++ int temporal_id; /* temporal ID of the picture */ ++ dma_addr_t rd_ptr; /* stream buffer read pointer for the current decoder instance */ ++ dma_addr_t wr_ptr; /* stream buffer write pointer for the current decoder instance */ ++ struct frame_buffer disp_frame; ++ u32 frame_display_flag; /* it reports a frame buffer flag to be displayed */ ++ /** ++ * this variable reports that sequence has been changed while H.264/AVC stream decoding. ++ * if it is 1, HOST application can get the new sequence information by calling ++ * vpu_dec_get_initial_info() or wave5_vpu_dec_issue_seq_init(). ++ * ++ * for H.265/HEVC decoder, each bit has a different meaning as follows. ++ * ++ * sequence_changed[5] : it indicates that the profile_idc has been changed ++ * sequence_changed[16] : it indicates that the resolution has been changed ++ * sequence_changed[19] : it indicates that the required number of frame buffer has ++ * been changed. ++ */ ++ unsigned int frame_cycle; /* reports the number of cycles for processing a frame */ ++ u32 sequence_no; ++ ++ u32 dec_host_cmd_tick; /* tick of DEC_PIC command for the picture */ ++ u32 dec_decode_end_tick; /* end tick of decoding slices of the picture */ ++ ++ u32 sequence_changed; ++}; ++ ++struct queue_status_info { ++ u32 instance_queue_count; ++ u32 report_queue_count; ++}; ++ ++/* ++ * encode struct and definition ++ */ ++ ++#define MAX_NUM_TEMPORAL_LAYER 7 ++#define MAX_NUM_SPATIAL_LAYER 3 ++#define MAX_GOP_NUM 8 ++ ++struct custom_gop_pic_param { ++ u32 pic_type; /* picture type of nth picture in the custom GOP */ ++ u32 poc_offset; /* POC of nth picture in the custom GOP */ ++ u32 pic_qp; /* quantization parameter of nth picture in the custom GOP */ ++ u32 use_multi_ref_p; /* use multiref pic for P picture. valid only if PIC_TYPE is P */ ++ u32 ref_poc_l0; /* POC of reference L0 of nth picture in the custom GOP */ ++ u32 ref_poc_l1; /* POC of reference L1 of nth picture in the custom GOP */ ++ s32 temporal_id; /* temporal ID of nth picture in the custom GOP */ ++}; ++ ++struct enc_wave_param { ++ /* ++ * profile indicator (HEVC only) ++ * ++ * 0 : the firmware determines a profile according to the internal_bit_depth ++ * 1 : main profile ++ * 2 : main10 profile ++ * 3 : main still picture profile ++ * In the AVC encoder, a profile cannot be set by the host application. ++ * The firmware decides it based on internal_bit_depth. ++ * profile = HIGH (bitdepth 8) profile = HIGH10 (bitdepth 10) ++ */ ++ u32 profile; ++ u32 level; /* level indicator (level * 10) */ ++ u32 internal_bit_depth: 4; /* 8/10 */ ++ u32 gop_preset_idx: 4; /* 0 - 9 */ ++ u32 decoding_refresh_type: 2; /* 0=non-IRAP, 1=CRA, 2=IDR */ ++ u32 intra_qp; /* quantization parameter of intra picture */ ++ u32 intra_period; /* period of intra picture in GOP size */ ++ u32 conf_win_top; /* top offset of conformance window */ ++ u32 conf_win_bot; /* bottom offset of conformance window */ ++ u32 conf_win_left; /* left offset of conformance window */ ++ u32 conf_win_right; /* right offset of conformance window */ ++ u32 intra_refresh_mode: 3; ++ /* ++ * Argument for intra_ctu_refresh_mode. ++ * ++ * Depending on intra_refresh_mode, it can mean one of the following: ++ * - intra_ctu_refresh_mode (1) -> number of consecutive CTU rows ++ * - intra_ctu_refresh_mode (2) -> the number of consecutive CTU columns ++ * - intra_ctu_refresh_mode (3) -> step size in CTU ++ * - intra_ctu_refresh_mode (4) -> number of intra ct_us to be encoded in a picture ++ */ ++ u32 intra_refresh_arg; ++ /* ++ * 0 : custom setting ++ * 1 : recommended encoder parameters (slow encoding speed, highest picture quality) ++ * 2 : boost mode (normal encoding speed, moderate picture quality) ++ * 3 : fast mode (fast encoding speed, low picture quality) ++ */ ++ u32 depend_slice_mode : 2; ++ u32 depend_slice_mode_arg; ++ u32 independ_slice_mode : 1; /* 0=no-multi-slice, 1=slice-in-ctu-number*/ ++ u32 independ_slice_mode_arg; ++ u32 max_num_merge: 2; ++ s32 beta_offset_div2: 4; /* sets beta_offset_div2 for deblocking filter */ ++ s32 tc_offset_div2: 4; /* sets tc_offset_div3 for deblocking filter */ ++ u32 hvs_qp_scale: 4; /* QP scaling factor for CU QP adjust if hvs_qp_scale_enable is 1 */ ++ u32 hvs_max_delta_qp; /* maximum delta QP for HVS */ ++ s32 chroma_cb_qp_offset; /* the value of chroma(cb) QP offset */ ++ s32 chroma_cr_qp_offset; /* the value of chroma(cr) QP offset */ ++ s32 initial_rc_qp; ++ u32 nr_intra_weight_y; ++ u32 nr_intra_weight_cb; /* weight to cb noise level for intra picture (0 ~ 31) */ ++ u32 nr_intra_weight_cr; /* weight to cr noise level for intra picture (0 ~ 31) */ ++ u32 nr_inter_weight_y; ++ u32 nr_inter_weight_cb; /* weight to cb noise level for inter picture (0 ~ 31) */ ++ u32 nr_inter_weight_cr; /* weight to cr noise level for inter picture (0 ~ 31) */ ++ u32 min_qp_i; /* minimum QP of I picture for rate control */ ++ u32 max_qp_i; /* maximum QP of I picture for rate control */ ++ u32 min_qp_p; /* minimum QP of P picture for rate control */ ++ u32 max_qp_p; /* maximum QP of P picture for rate control */ ++ u32 min_qp_b; /* minimum QP of B picture for rate control */ ++ u32 max_qp_b; /* maximum QP of B picture for rate control */ ++ u32 avc_idr_period; /* period of IDR picture (0 ~ 1024). 0 - implies an infinite period */ ++ u32 avc_slice_arg; /* the number of MB for a slice when avc_slice_mode is set with 1 */ ++ u32 intra_mb_refresh_mode: 2; /* 0=none, 1=row, 2=column, 3=step-size-in-mb */ ++ /** ++ * Argument for intra_mb_refresh_mode. ++ * ++ * intra_mb_refresh_mode (1) -> number of consecutive MB rows ++ * intra_mb_refresh_mode (2) ->the number of consecutive MB columns ++ * intra_mb_refresh_mode (3) -> step size in MB ++ */ ++ u32 intra_mb_refresh_arg; ++ u32 rc_weight_param; ++ u32 rc_weight_buf; ++ ++ /* flags */ ++ u32 en_still_picture: 1; /* still picture profile */ ++ u32 tier: 1; /* 0=main, 1=high */ ++ u32 avc_slice_mode: 1; /* 0=none, 1=slice-in-mb-number */ ++ u32 entropy_coding_mode: 1; /* 0=CAVLC, 1=CABAC */ ++ u32 lossless_enable: 1; /* enable lossless encoding */ ++ u32 const_intra_pred_flag: 1; /* enable constrained intra prediction */ ++ u32 tmvp_enable: 1; /* enable temporal motion vector prediction */ ++ u32 wpp_enable: 1; ++ u32 disable_deblk: 1; /* disable in-loop deblocking filtering */ ++ u32 lf_cross_slice_boundary_enable: 1; ++ u32 skip_intra_trans: 1; ++ u32 sao_enable: 1; /* enable SAO (sample adaptive offset) */ ++ u32 intra_nx_n_enable: 1; /* enables intra nx_n p_us */ ++ u32 cu_level_rc_enable: 1; /* enable CU level rate control */ ++ u32 hvs_qp_enable: 1; /* enable CU QP adjustment for subjective quality enhancement */ ++ u32 strong_intra_smooth_enable: 1; /* enable strong intra smoothing */ ++ u32 rdo_skip: 1; /* skip RDO (rate distortion optimization) */ ++ u32 lambda_scaling_enable: 1; /* enable lambda scaling using custom GOP */ ++ u32 transform8x8_enable: 1; /* enable 8x8 intra prediction and 8x8 transform */ ++ u32 mb_level_rc_enable: 1; /* enable MB-level rate control */ ++}; ++ ++struct enc_open_param { ++ dma_addr_t bitstream_buffer; ++ unsigned int bitstream_buffer_size; ++ u32 pic_width; /* width of a picture to be encoded in unit of sample */ ++ u32 pic_height; /* height of a picture to be encoded in unit of sample */ ++ u32 frame_rate_info;/* desired fps */ ++ u32 vbv_buffer_size; ++ u32 bit_rate; /* target bitrate in bps */ ++ struct enc_wave_param wave_param; ++ enum packed_format_num packed_format; /* <> */ ++ enum frame_buffer_format src_format; ++ bool line_buf_int_en; ++ u32 rc_enable : 1; /* rate control */ ++}; ++ ++struct enc_initial_info { ++ u32 min_frame_buffer_count; /* minimum number of frame buffers */ ++ u32 min_src_frame_count; /* minimum number of source buffers */ ++ u32 seq_init_err_reason; ++ u32 warn_info; ++ u32 vlc_buf_size; /* size of task buffer */ ++ u32 param_buf_size; /* size of task buffer */ ++}; ++ ++/* ++ * Flags to encode NAL units explicitly ++ */ ++struct enc_code_opt { ++ u32 implicit_header_encode: 1; ++ u32 encode_vcl: 1; ++ u32 encode_vps: 1; ++ u32 encode_sps: 1; ++ u32 encode_pps: 1; ++ u32 encode_aud: 1; ++ u32 encode_eos: 1; ++ u32 encode_eob: 1; ++ u32 encode_vui: 1; ++}; ++ ++struct enc_param { ++ struct frame_buffer *source_frame; ++ u32 pic_stream_buffer_addr; ++ u64 pic_stream_buffer_size; ++ u32 src_idx; /* source frame buffer index */ ++ struct enc_code_opt code_option; ++ u64 pts; /* presentation timestamp (PTS) of the input source */ ++ bool src_end_flag; ++}; ++ ++struct enc_output_info { ++ u32 bitstream_buffer; ++ u32 bitstream_size; /* byte size of encoded bitstream */ ++ u32 pic_type: 2; /* <> */ ++ s32 recon_frame_index; ++ dma_addr_t rd_ptr; ++ dma_addr_t wr_ptr; ++ u32 enc_pic_byte; /* number of encoded picture bytes */ ++ s32 enc_src_idx; /* source buffer index of the currently encoded picture */ ++ u32 enc_vcl_nut; ++ u32 error_reason; /* error reason of the currently encoded picture */ ++ u32 warn_info; /* warning information on the currently encoded picture */ ++ unsigned int frame_cycle; /* param for reporting the cycle number of encoding one frame*/ ++ u64 pts; ++ u32 enc_host_cmd_tick; /* tick of ENC_PIC command for the picture */ ++ u32 enc_encode_end_tick; /* end tick of encoding slices of the picture */ ++}; ++ ++enum enc_pic_code_option { ++ CODEOPT_ENC_HEADER_IMPLICIT = BIT(0), ++ CODEOPT_ENC_VCL = BIT(1), /* flag to encode VCL nal unit explicitly */ ++}; ++ ++enum gop_preset_idx { ++ PRESET_IDX_CUSTOM_GOP = 0, /* user defined GOP structure */ ++ PRESET_IDX_ALL_I = 1, /* all intra, gopsize = 1 */ ++ PRESET_IDX_IPP = 2, /* consecutive P, cyclic gopsize = 1 */ ++ PRESET_IDX_IBBB = 3, /* consecutive B, cyclic gopsize = 1 */ ++ PRESET_IDX_IBPBP = 4, /* gopsize = 2 */ ++ PRESET_IDX_IBBBP = 5, /* gopsize = 4 */ ++ PRESET_IDX_IPPPP = 6, /* consecutive P, cyclic gopsize = 4 */ ++ PRESET_IDX_IBBBB = 7, /* consecutive B, cyclic gopsize = 4 */ ++ PRESET_IDX_RA_IB = 8, /* random access, cyclic gopsize = 8 */ ++ PRESET_IDX_IPP_SINGLE = 9, /* consecutive P, cyclic gopsize = 1, with single ref */ ++}; ++ ++struct sec_axi_info { ++ u32 use_ip_enable; ++ u32 use_bit_enable; ++ u32 use_lf_row_enable: 1; ++ u32 use_enc_rdo_enable: 1; ++ u32 use_enc_lf_enable: 1; ++}; ++ ++struct dec_info { ++ struct dec_open_param open_param; ++ struct dec_initial_info initial_info; ++ struct dec_initial_info new_seq_info; /* temporal new sequence information */ ++ u32 stream_wr_ptr; ++ u32 stream_rd_ptr; ++ u32 frame_display_flag; ++ dma_addr_t stream_buf_start_addr; ++ dma_addr_t stream_buf_end_addr; ++ u32 stream_buf_size; ++ struct vpu_buf vb_mv[MAX_REG_FRAME]; ++ struct vpu_buf vb_fbc_y_tbl[MAX_REG_FRAME]; ++ struct vpu_buf vb_fbc_c_tbl[MAX_REG_FRAME]; ++ unsigned int num_of_decoding_fbs: 7; ++ unsigned int num_of_display_fbs: 7; ++ unsigned int stride; ++ struct sec_axi_info sec_axi_info; ++ dma_addr_t user_data_buf_addr; ++ u32 user_data_enable; ++ u32 user_data_buf_size; ++ struct vpu_buf vb_work; ++ struct vpu_buf vb_task; ++ struct dec_output_info dec_out_info[WAVE5_MAX_FBS]; ++ u32 seq_change_mask; ++ enum temporal_id_mode temp_id_select_mode; ++ u32 target_temp_id; ++ u32 target_spatial_id; ++ u32 instance_queue_count; ++ u32 report_queue_count; ++ u32 cycle_per_tick; ++ u32 product_code; ++ u32 vlc_buf_size; ++ u32 param_buf_size; ++ bool initial_info_obtained; ++ bool reorder_enable; ++ bool first_cycle_check; ++ u32 stream_endflag: 1; ++}; ++ ++struct enc_info { ++ struct enc_open_param open_param; ++ struct enc_initial_info initial_info; ++ u32 stream_rd_ptr; ++ u32 stream_wr_ptr; ++ dma_addr_t stream_buf_start_addr; ++ dma_addr_t stream_buf_end_addr; ++ u32 stream_buf_size; ++ unsigned int num_frame_buffers; ++ unsigned int stride; ++ bool rotation_enable; ++ bool mirror_enable; ++ enum mirror_direction mirror_direction; ++ unsigned int rotation_angle; ++ bool initial_info_obtained; ++ struct sec_axi_info sec_axi_info; ++ bool line_buf_int_en; ++ struct vpu_buf vb_work; ++ struct vpu_buf vb_mv; /* col_mv buffer */ ++ struct vpu_buf vb_fbc_y_tbl; /* FBC luma table buffer */ ++ struct vpu_buf vb_fbc_c_tbl; /* FBC chroma table buffer */ ++ struct vpu_buf vb_sub_sam_buf; /* sub-sampled buffer for ME */ ++ struct vpu_buf vb_task; ++ u64 cur_pts; /* current timestamp in 90_k_hz */ ++ u64 pts_map[32]; /* PTS mapped with source frame index */ ++ u32 instance_queue_count; ++ u32 report_queue_count; ++ bool first_cycle_check; ++ u32 cycle_per_tick; ++ u32 product_code; ++ u32 vlc_buf_size; ++ u32 param_buf_size; ++}; ++ ++struct vpu_device { ++ struct device *dev; ++ struct v4l2_device v4l2_dev; ++ struct v4l2_m2m_dev *v4l2_m2m_dec_dev; ++ struct v4l2_m2m_dev *v4l2_m2m_enc_dev; ++ struct list_head instances; ++ struct video_device *video_dev_dec; ++ struct video_device *video_dev_enc; ++ struct mutex dev_lock; /* lock for the src, dst v4l2 queues */ ++ struct mutex hw_lock; /* lock hw configurations */ ++ int irq; ++ enum product_id product; ++ struct vpu_attr attr; ++ struct vpu_buf common_mem; ++ u32 last_performance_cycles; ++ u32 sram_size; ++ struct gen_pool *sram_pool; ++ struct vpu_buf sram_buf; ++ void __iomem *vdb_register; ++ u32 product_code; ++ struct ida inst_ida; ++ struct clk_bulk_data *clks; ++ int num_clks; ++}; ++ ++struct vpu_instance; ++ ++struct vpu_instance_ops { ++ void (*finish_process)(struct vpu_instance *inst); ++}; ++ ++struct vpu_instance { ++ struct list_head list; ++ struct v4l2_fh v4l2_fh; ++ struct v4l2_m2m_dev *v4l2_m2m_dev; ++ struct v4l2_ctrl_handler v4l2_ctrl_hdl; ++ struct vpu_device *dev; ++ struct completion irq_done; ++ ++ struct v4l2_pix_format_mplane src_fmt; ++ struct v4l2_pix_format_mplane dst_fmt; ++ enum v4l2_colorspace colorspace; ++ enum v4l2_xfer_func xfer_func; ++ enum v4l2_ycbcr_encoding ycbcr_enc; ++ enum v4l2_quantization quantization; ++ ++ enum vpu_instance_state state; ++ enum vpu_instance_type type; ++ const struct vpu_instance_ops *ops; ++ spinlock_t state_spinlock; /* This protects the instance state */ ++ ++ enum wave_std std; ++ s32 id; ++ union { ++ struct enc_info enc_info; ++ struct dec_info dec_info; ++ } *codec_info; ++ struct frame_buffer frame_buf[MAX_REG_FRAME]; ++ struct vpu_buf frame_vbuf[MAX_REG_FRAME]; ++ u32 fbc_buf_count; ++ u32 queued_src_buf_num; ++ u32 queued_dst_buf_num; ++ struct list_head avail_src_bufs; ++ struct list_head avail_dst_bufs; ++ struct v4l2_rect conf_win; ++ u64 timestamp; ++ enum frame_buffer_format output_format; ++ bool cbcr_interleave; ++ bool nv21; ++ bool eos; ++ struct vpu_buf bitstream_vbuf; ++ dma_addr_t last_rd_ptr; ++ size_t remaining_consumed_bytes; ++ bool needs_reallocation; ++ ++ unsigned int min_src_buf_count; ++ unsigned int rot_angle; ++ unsigned int mirror_direction; ++ unsigned int bit_depth; ++ unsigned int frame_rate; ++ unsigned int vbv_buf_size; ++ unsigned int rc_mode; ++ unsigned int rc_enable; ++ unsigned int bit_rate; ++ unsigned int encode_aud; ++ struct enc_wave_param enc_param; ++}; ++ ++void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data); ++u32 wave5_vdi_read_register(struct vpu_device *vpu_dev, u32 addr); ++int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb); ++int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb); ++int wave5_vdi_allocate_array(struct vpu_device *vpu_dev, struct vpu_buf *array, unsigned int count, ++ size_t size); ++int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset, ++ u8 *data, size_t len); ++int wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb); ++void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev); ++void wave5_vdi_free_sram(struct vpu_device *vpu_dev); ++ ++int wave5_vpu_init_with_bitcode(struct device *dev, u8 *bitcode, size_t size); ++int wave5_vpu_flush_instance(struct vpu_instance *inst); ++int wave5_vpu_get_version_info(struct device *dev, u32 *revision, unsigned int *product_id); ++int wave5_vpu_dec_open(struct vpu_instance *inst, struct dec_open_param *open_param); ++int wave5_vpu_dec_close(struct vpu_instance *inst, u32 *fail_res); ++int wave5_vpu_dec_issue_seq_init(struct vpu_instance *inst); ++int wave5_vpu_dec_complete_seq_init(struct vpu_instance *inst, struct dec_initial_info *info); ++int wave5_vpu_dec_register_frame_buffer_ex(struct vpu_instance *inst, int num_of_decoding_fbs, ++ int num_of_display_fbs, int stride, int height); ++int wave5_vpu_dec_start_one_frame(struct vpu_instance *inst, u32 *res_fail); ++int wave5_vpu_dec_get_output_info(struct vpu_instance *inst, struct dec_output_info *info); ++int wave5_vpu_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr, int update_wr_ptr); ++dma_addr_t wave5_vpu_dec_get_rd_ptr(struct vpu_instance *inst); ++int wave5_vpu_dec_reset_framebuffer(struct vpu_instance *inst, unsigned int index); ++int wave5_vpu_dec_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter); ++int wave5_vpu_dec_get_bitstream_buffer(struct vpu_instance *inst, dma_addr_t *prd_ptr, ++ dma_addr_t *pwr_ptr, size_t *size); ++int wave5_vpu_dec_update_bitstream_buffer(struct vpu_instance *inst, size_t size); ++int wave5_vpu_dec_clr_disp_flag(struct vpu_instance *inst, int index); ++int wave5_vpu_dec_set_disp_flag(struct vpu_instance *inst, int index); ++ ++int wave5_vpu_enc_open(struct vpu_instance *inst, struct enc_open_param *open_param); ++int wave5_vpu_enc_close(struct vpu_instance *inst, u32 *fail_res); ++int wave5_vpu_enc_issue_seq_init(struct vpu_instance *inst); ++int wave5_vpu_enc_complete_seq_init(struct vpu_instance *inst, struct enc_initial_info *info); ++int wave5_vpu_enc_register_frame_buffer(struct vpu_instance *inst, unsigned int num, ++ unsigned int stride, int height, ++ enum tiled_map_type map_type); ++int wave5_vpu_enc_start_one_frame(struct vpu_instance *inst, struct enc_param *param, ++ u32 *fail_res); ++int wave5_vpu_enc_get_output_info(struct vpu_instance *inst, struct enc_output_info *info); ++int wave5_vpu_enc_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter); ++ ++#endif +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpu.c b/drivers/media/platform/chips-media/wave5/wave5-vpu.c +--- a/drivers/media/platform/chips-media/wave5/wave5-vpu.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,291 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) ++/* ++ * Wave5 series multi-standard codec IP - platform driver ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "wave5-vpu.h" ++#include "wave5-regdefine.h" ++#include "wave5-vpuconfig.h" ++#include "wave5.h" ++ ++#define VPU_PLATFORM_DEVICE_NAME "vdec" ++#define VPU_CLK_NAME "vcodec" ++ ++#define WAVE5_IS_ENC BIT(0) ++#define WAVE5_IS_DEC BIT(1) ++ ++struct wave5_match_data { ++ int flags; ++ const char *fw_name; ++}; ++ ++int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout) ++{ ++ int ret; ++ ++ ret = wait_for_completion_timeout(&inst->irq_done, ++ msecs_to_jiffies(timeout)); ++ if (!ret) ++ return -ETIMEDOUT; ++ ++ reinit_completion(&inst->irq_done); ++ ++ return 0; ++} ++ ++static irqreturn_t wave5_vpu_irq_thread(int irq, void *dev_id) ++{ ++ u32 seq_done; ++ u32 cmd_done; ++ u32 irq_reason; ++ struct vpu_instance *inst; ++ struct vpu_device *dev = dev_id; ++ ++ if (wave5_vdi_read_register(dev, W5_VPU_VPU_INT_STS)) { ++ irq_reason = wave5_vdi_read_register(dev, W5_VPU_VINT_REASON); ++ wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_CLR, irq_reason); ++ wave5_vdi_write_register(dev, W5_VPU_VINT_CLEAR, 0x1); ++ ++ list_for_each_entry(inst, &dev->instances, list) { ++ seq_done = wave5_vdi_read_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO); ++ cmd_done = wave5_vdi_read_register(dev, W5_RET_QUEUE_CMD_DONE_INST); ++ ++ if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) || ++ irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) { ++ if (seq_done & BIT(inst->id)) { ++ seq_done &= ~BIT(inst->id); ++ wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO, ++ seq_done); ++ complete(&inst->irq_done); ++ } ++ } ++ ++ if (irq_reason & BIT(INT_WAVE5_DEC_PIC) || ++ irq_reason & BIT(INT_WAVE5_ENC_PIC)) { ++ if (cmd_done & BIT(inst->id)) { ++ cmd_done &= ~BIT(inst->id); ++ wave5_vdi_write_register(dev, W5_RET_QUEUE_CMD_DONE_INST, ++ cmd_done); ++ inst->ops->finish_process(inst); ++ } ++ } ++ ++ wave5_vpu_clear_interrupt(inst, irq_reason); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int wave5_vpu_load_firmware(struct device *dev, const char *fw_name, ++ u32 *revision) ++{ ++ const struct firmware *fw; ++ int ret; ++ unsigned int product_id; ++ ++ ret = request_firmware(&fw, fw_name, dev); ++ if (ret) { ++ dev_err(dev, "request_firmware, fail: %d\n", ret); ++ return ret; ++ } ++ ++ ret = wave5_vpu_init_with_bitcode(dev, (u8 *)fw->data, fw->size); ++ if (ret) { ++ dev_err(dev, "vpu_init_with_bitcode, fail: %d\n", ret); ++ release_firmware(fw); ++ return ret; ++ } ++ release_firmware(fw); ++ ++ ret = wave5_vpu_get_version_info(dev, revision, &product_id); ++ if (ret) { ++ dev_err(dev, "vpu_get_version_info fail: %d\n", ret); ++ return ret; ++ } ++ ++ dev_dbg(dev, "%s: enum product_id: %08x, fw revision: %u\n", ++ __func__, product_id, *revision); ++ ++ return 0; ++} ++ ++static int wave5_vpu_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct vpu_device *dev; ++ const struct wave5_match_data *match_data; ++ u32 fw_revision; ++ ++ match_data = device_get_match_data(&pdev->dev); ++ if (!match_data) { ++ dev_err(&pdev->dev, "missing device match data\n"); ++ return -EINVAL; ++ } ++ ++ /* physical addresses limited to 32 bits */ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); ++ if (ret) { ++ dev_err(&pdev->dev, "Failed to set DMA mask: %d\n", ret); ++ return ret; ++ } ++ ++ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ ++ dev->vdb_register = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(dev->vdb_register)) ++ return PTR_ERR(dev->vdb_register); ++ ida_init(&dev->inst_ida); ++ ++ mutex_init(&dev->dev_lock); ++ mutex_init(&dev->hw_lock); ++ dev_set_drvdata(&pdev->dev, dev); ++ dev->dev = &pdev->dev; ++ ++ ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks); ++ ++ /* continue without clock, assume externally managed */ ++ if (ret < 0) { ++ dev_warn(&pdev->dev, "Getting clocks, fail: %d\n", ret); ++ ret = 0; ++ } ++ dev->num_clks = ret; ++ ++ ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks); ++ if (ret) { ++ dev_err(&pdev->dev, "Enabling clocks, fail: %d\n", ret); ++ return ret; ++ } ++ ++ ret = of_property_read_u32(pdev->dev.of_node, "sram-size", ++ &dev->sram_size); ++ if (ret) { ++ dev_warn(&pdev->dev, "sram-size not found\n"); ++ dev->sram_size = 0; ++ } ++ ++ dev->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0); ++ if (!dev->sram_pool) ++ dev_warn(&pdev->dev, "sram node not found\n"); ++ ++ dev->product_code = wave5_vdi_read_register(dev, VPU_PRODUCT_CODE_REGISTER); ++ ret = wave5_vdi_init(&pdev->dev); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "wave5_vdi_init, fail: %d\n", ret); ++ goto err_clk_dis; ++ } ++ dev->product = wave5_vpu_get_product_id(dev); ++ ++ INIT_LIST_HEAD(&dev->instances); ++ ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); ++ if (ret) { ++ dev_err(&pdev->dev, "v4l2_device_register, fail: %d\n", ret); ++ goto err_vdi_release; ++ } ++ ++ if (match_data->flags & WAVE5_IS_DEC) { ++ ret = wave5_vpu_dec_register_device(dev); ++ if (ret) { ++ dev_err(&pdev->dev, "wave5_vpu_dec_register_device, fail: %d\n", ret); ++ goto err_v4l2_unregister; ++ } ++ } ++ if (match_data->flags & WAVE5_IS_ENC) { ++ ret = wave5_vpu_enc_register_device(dev); ++ if (ret) { ++ dev_err(&pdev->dev, "wave5_vpu_enc_register_device, fail: %d\n", ret); ++ goto err_dec_unreg; ++ } ++ } ++ ++ dev->irq = platform_get_irq(pdev, 0); ++ if (dev->irq < 0) { ++ dev_err(&pdev->dev, "failed to get irq resource\n"); ++ ret = -ENXIO; ++ goto err_enc_unreg; ++ } ++ ++ ret = devm_request_threaded_irq(&pdev->dev, dev->irq, NULL, ++ wave5_vpu_irq_thread, IRQF_ONESHOT, "vpu_irq", dev); ++ if (ret) { ++ dev_err(&pdev->dev, "Register interrupt handler, fail: %d\n", ret); ++ goto err_enc_unreg; ++ } ++ ++ ret = wave5_vpu_load_firmware(&pdev->dev, match_data->fw_name, &fw_revision); ++ if (ret) { ++ dev_err(&pdev->dev, "wave5_vpu_load_firmware, fail: %d\n", ret); ++ goto err_enc_unreg; ++ } ++ ++ dev_info(&pdev->dev, "Added wave5 driver with caps: %s %s\n", ++ (match_data->flags & WAVE5_IS_ENC) ? "'ENCODE'" : "", ++ (match_data->flags & WAVE5_IS_DEC) ? "'DECODE'" : ""); ++ dev_info(&pdev->dev, "Product Code: 0x%x\n", dev->product_code); ++ dev_info(&pdev->dev, "Firmware Revision: %u\n", fw_revision); ++ return 0; ++ ++err_enc_unreg: ++ if (match_data->flags & WAVE5_IS_ENC) ++ wave5_vpu_enc_unregister_device(dev); ++err_dec_unreg: ++ if (match_data->flags & WAVE5_IS_DEC) ++ wave5_vpu_dec_unregister_device(dev); ++err_v4l2_unregister: ++ v4l2_device_unregister(&dev->v4l2_dev); ++err_vdi_release: ++ wave5_vdi_release(&pdev->dev); ++err_clk_dis: ++ clk_bulk_disable_unprepare(dev->num_clks, dev->clks); ++ ++ return ret; ++} ++ ++static int wave5_vpu_remove(struct platform_device *pdev) ++{ ++ struct vpu_device *dev = dev_get_drvdata(&pdev->dev); ++ ++ mutex_destroy(&dev->dev_lock); ++ mutex_destroy(&dev->hw_lock); ++ clk_bulk_disable_unprepare(dev->num_clks, dev->clks); ++ wave5_vpu_enc_unregister_device(dev); ++ wave5_vpu_dec_unregister_device(dev); ++ v4l2_device_unregister(&dev->v4l2_dev); ++ wave5_vdi_release(&pdev->dev); ++ ida_destroy(&dev->inst_ida); ++ ++ return 0; ++} ++ ++static const struct wave5_match_data ti_wave521c_data = { ++ .flags = WAVE5_IS_ENC | WAVE5_IS_DEC, ++ .fw_name = "cnm/wave521c_k3_codec_fw.bin", ++}; ++ ++static const struct of_device_id wave5_dt_ids[] = { ++ { .compatible = "ti,j721s2-wave521c", .data = &ti_wave521c_data }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, wave5_dt_ids); ++ ++static struct platform_driver wave5_vpu_driver = { ++ .driver = { ++ .name = VPU_PLATFORM_DEVICE_NAME, ++ .of_match_table = of_match_ptr(wave5_dt_ids), ++ }, ++ .probe = wave5_vpu_probe, ++ .remove = wave5_vpu_remove, ++}; ++ ++module_platform_driver(wave5_vpu_driver); ++MODULE_DESCRIPTION("chips&media VPU V4L2 driver"); ++MODULE_LICENSE("Dual BSD/GPL"); +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h +--- a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,77 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ ++/* ++ * Wave5 series multi-standard codec IP - product config definitions ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#ifndef _VPU_CONFIG_H_ ++#define _VPU_CONFIG_H_ ++ ++#define WAVE517_CODE 0x5170 ++#define WAVE537_CODE 0x5370 ++#define WAVE511_CODE 0x5110 ++#define WAVE521_CODE 0x5210 ++#define WAVE521C_CODE 0x521c ++#define WAVE521C_DUAL_CODE 0x521d // wave521 dual core ++#define WAVE521E1_CODE 0x5211 ++ ++#define PRODUCT_CODE_W_SERIES(x) ({ \ ++ int c = x; \ ++ ((c) == WAVE517_CODE || (c) == WAVE537_CODE || \ ++ (c) == WAVE511_CODE || (c) == WAVE521_CODE || \ ++ (c) == WAVE521E1_CODE || (c) == WAVE521C_CODE || \ ++ (c) == WAVE521C_DUAL_CODE); \ ++}) ++ ++#define WAVE517_WORKBUF_SIZE (2 * 1024 * 1024) ++#define WAVE521ENC_WORKBUF_SIZE (128 * 1024) //HEVC 128K, AVC 40K ++#define WAVE521DEC_WORKBUF_SIZE (1784 * 1024) ++ ++#define MAX_NUM_INSTANCE 32 ++ ++#define W5_MIN_ENC_PIC_WIDTH 256 ++#define W5_MIN_ENC_PIC_HEIGHT 128 ++#define W5_MAX_ENC_PIC_WIDTH 8192 ++#define W5_MAX_ENC_PIC_HEIGHT 8192 ++ ++// application specific configuration ++#define VPU_ENC_TIMEOUT 60000 ++#define VPU_DEC_TIMEOUT 60000 ++ ++// for WAVE encoder ++#define USE_SRC_PRP_AXI 0 ++#define USE_SRC_PRI_AXI 1 ++#define DEFAULT_SRC_AXI USE_SRC_PRP_AXI ++ ++/************************************************************************/ ++/* VPU COMMON MEMORY */ ++/************************************************************************/ ++#define VLC_BUF_NUM (2) ++ ++#define COMMAND_QUEUE_DEPTH (2) ++ ++#define W5_REMAP_INDEX0 0 ++#define W5_REMAP_INDEX1 1 ++#define W5_REMAP_MAX_SIZE (1024 * 1024) ++ ++#define WAVE5_MAX_CODE_BUF_SIZE (2 * 1024 * 1024) ++#define WAVE5_TEMPBUF_OFFSET WAVE5_MAX_CODE_BUF_SIZE ++#define WAVE5_TEMPBUF_SIZE (1024 * 1024) ++ ++#define SIZE_COMMON (WAVE5_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE) ++ ++//=====4. VPU REPORT MEMORY ======================// ++ ++#define WAVE5_UPPER_PROC_AXI_ID 0x0 ++ ++#define WAVE5_PROC_AXI_ID 0x0 ++#define WAVE5_PRP_AXI_ID 0x0 ++#define WAVE5_FBD_Y_AXI_ID 0x0 ++#define WAVE5_FBC_Y_AXI_ID 0x0 ++#define WAVE5_FBD_C_AXI_ID 0x0 ++#define WAVE5_FBC_C_AXI_ID 0x0 ++#define WAVE5_SEC_AXI_ID 0x0 ++#define WAVE5_PRI_AXI_ID 0x0 ++ ++#endif /* _VPU_CONFIG_H_ */ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +--- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,1932 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) ++/* ++ * Wave5 series multi-standard codec IP - decoder interface ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#include "wave5-helper.h" ++ ++#define VPU_DEC_DEV_NAME "C&M Wave5 VPU decoder" ++#define VPU_DEC_DRV_NAME "wave5-dec" ++ ++#define DEFAULT_SRC_SIZE(width, height) ({ \ ++ (width) * (height) / 8 * 3; \ ++}) ++ ++static const struct vpu_format dec_fmt_list[FMT_TYPES][MAX_FMTS] = { ++ [VPU_FMT_TYPE_CODEC] = { ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_HEVC, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_H264, ++ .max_width = 8192, ++ .min_width = 32, ++ .max_height = 4320, ++ .min_height = 32, ++ }, ++ }, ++ [VPU_FMT_TYPE_RAW] = { ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV12, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV21, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV422P, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV16, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV61, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV12M, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV21M, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV422M, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV16M, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV61M, ++ .max_width = 8192, ++ .min_width = 8, ++ .max_height = 4320, ++ .min_height = 8, ++ }, ++ } ++}; ++ ++/* ++ * Make sure that the state switch is allowed and add logging for debugging ++ * purposes ++ */ ++static int switch_state(struct vpu_instance *inst, enum vpu_instance_state state) ++{ ++ switch (state) { ++ case VPU_INST_STATE_NONE: ++ break; ++ case VPU_INST_STATE_OPEN: ++ if (inst->state != VPU_INST_STATE_NONE) ++ goto invalid_state_switch; ++ goto valid_state_switch; ++ case VPU_INST_STATE_INIT_SEQ: ++ if (inst->state != VPU_INST_STATE_OPEN && inst->state != VPU_INST_STATE_STOP) ++ goto invalid_state_switch; ++ goto valid_state_switch; ++ case VPU_INST_STATE_PIC_RUN: ++ if (inst->state != VPU_INST_STATE_INIT_SEQ) ++ goto invalid_state_switch; ++ goto valid_state_switch; ++ case VPU_INST_STATE_STOP: ++ goto valid_state_switch; ++ } ++invalid_state_switch: ++ WARN(1, "Invalid state switch from %s to %s.\n", ++ state_to_str(inst->state), state_to_str(state)); ++ return -EINVAL; ++valid_state_switch: ++ dev_dbg(inst->dev->dev, "Switch state from %s to %s.\n", ++ state_to_str(inst->state), state_to_str(state)); ++ inst->state = state; ++ return 0; ++} ++ ++static int wave5_vpu_dec_set_eos_on_firmware(struct vpu_instance *inst) ++{ ++ int ret; ++ ++ ret = wave5_vpu_dec_update_bitstream_buffer(inst, 0); ++ if (ret) { ++ /* ++ * To set the EOS flag, a command is sent to the firmware. ++ * That command may never return (timeout) or may report an error. ++ */ ++ dev_err(inst->dev->dev, ++ "Setting EOS for the bitstream, fail: %d\n", ret); ++ return ret; ++ } ++ return 0; ++} ++ ++static bool wave5_last_src_buffer_consumed(struct v4l2_m2m_ctx *m2m_ctx) ++{ ++ struct vpu_src_buffer *vpu_buf; ++ ++ if (!m2m_ctx->last_src_buf) ++ return false; ++ ++ vpu_buf = wave5_to_vpu_src_buf(m2m_ctx->last_src_buf); ++ return vpu_buf->consumed; ++} ++ ++static void wave5_handle_src_buffer(struct vpu_instance *inst, dma_addr_t rd_ptr) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct v4l2_m2m_buffer *buf, *n; ++ size_t consumed_bytes = 0; ++ ++ if (rd_ptr >= inst->last_rd_ptr) { ++ consumed_bytes = rd_ptr - inst->last_rd_ptr; ++ } else { ++ size_t rd_offs = rd_ptr - inst->bitstream_vbuf.daddr; ++ size_t last_rd_offs = inst->last_rd_ptr - inst->bitstream_vbuf.daddr; ++ ++ consumed_bytes = rd_offs + (inst->bitstream_vbuf.size - last_rd_offs); ++ } ++ ++ inst->last_rd_ptr = rd_ptr; ++ consumed_bytes += inst->remaining_consumed_bytes; ++ ++ dev_dbg(inst->dev->dev, "%s: %zu bytes of bitstream was consumed", __func__, ++ consumed_bytes); ++ ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { ++ struct vb2_v4l2_buffer *src_buf = &buf->vb; ++ size_t src_size = vb2_get_plane_payload(&src_buf->vb2_buf, 0); ++ ++ if (src_size > consumed_bytes) ++ break; ++ ++ dev_dbg(inst->dev->dev, "%s: removing src buffer %i", ++ __func__, src_buf->vb2_buf.index); ++ src_buf = v4l2_m2m_src_buf_remove(m2m_ctx); ++ inst->timestamp = src_buf->vb2_buf.timestamp; ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ consumed_bytes -= src_size; ++ ++ /* Handle the case the last bitstream buffer has been picked */ ++ if (src_buf == m2m_ctx->last_src_buf) { ++ int ret; ++ ++ m2m_ctx->last_src_buf = NULL; ++ ret = wave5_vpu_dec_set_eos_on_firmware(inst); ++ if (ret) ++ dev_warn(inst->dev->dev, ++ "Setting EOS for the bitstream, fail: %d\n", ret); ++ break; ++ } ++ } ++ ++ inst->remaining_consumed_bytes = consumed_bytes; ++} ++ ++static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned int width, ++ unsigned int height) ++{ ++ switch (pix_mp->pixelformat) { ++ case V4L2_PIX_FMT_YUV420: ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV21: ++ pix_mp->width = round_up(width, 32); ++ pix_mp->height = round_up(height, 16); ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = width * height * 3 / 2; ++ break; ++ case V4L2_PIX_FMT_YUV422P: ++ case V4L2_PIX_FMT_NV16: ++ case V4L2_PIX_FMT_NV61: ++ pix_mp->width = round_up(width, 32); ++ pix_mp->height = round_up(height, 16); ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = width * height * 2; ++ break; ++ case V4L2_PIX_FMT_YUV420M: ++ pix_mp->width = round_up(width, 32); ++ pix_mp->height = round_up(height, 16); ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = width * height; ++ pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2; ++ pix_mp->plane_fmt[1].sizeimage = width * height / 4; ++ pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2; ++ pix_mp->plane_fmt[2].sizeimage = width * height / 4; ++ break; ++ case V4L2_PIX_FMT_NV12M: ++ case V4L2_PIX_FMT_NV21M: ++ pix_mp->width = round_up(width, 32); ++ pix_mp->height = round_up(height, 16); ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = width * height; ++ pix_mp->plane_fmt[1].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[1].sizeimage = width * height / 2; ++ break; ++ case V4L2_PIX_FMT_YUV422M: ++ pix_mp->width = round_up(width, 32); ++ pix_mp->height = round_up(height, 16); ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = width * height; ++ pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2; ++ pix_mp->plane_fmt[1].sizeimage = width * height / 2; ++ pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2; ++ pix_mp->plane_fmt[2].sizeimage = width * height / 2; ++ break; ++ case V4L2_PIX_FMT_NV16M: ++ case V4L2_PIX_FMT_NV61M: ++ pix_mp->width = round_up(width, 32); ++ pix_mp->height = round_up(height, 16); ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = width * height; ++ pix_mp->plane_fmt[1].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[1].sizeimage = width * height; ++ break; ++ default: ++ pix_mp->width = width; ++ pix_mp->height = height; ++ pix_mp->plane_fmt[0].bytesperline = 0; ++ pix_mp->plane_fmt[0].sizeimage = max(DEFAULT_SRC_SIZE(width, height), ++ pix_mp->plane_fmt[0].sizeimage); ++ break; ++ } ++} ++ ++static int start_decode(struct vpu_instance *inst, u32 *fail_res) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ int ret = 0; ++ ++ ret = wave5_vpu_dec_start_one_frame(inst, fail_res); ++ if (ret) { ++ struct vb2_v4l2_buffer *src_buf; ++ ++ src_buf = v4l2_m2m_src_buf_remove(m2m_ctx); ++ if (src_buf) ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); ++ switch_state(inst, VPU_INST_STATE_STOP); ++ ++ dev_dbg(inst->dev->dev, "%s: pic run failed / finish job", __func__); ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++ } ++ ++ return ret; ++} ++ ++static void flag_last_buffer_done(struct vpu_instance *inst) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct vb2_v4l2_buffer *vb; ++ int i; ++ ++ lockdep_assert_held(&inst->state_spinlock); ++ ++ vb = v4l2_m2m_dst_buf_remove(m2m_ctx); ++ if (!vb) { ++ m2m_ctx->is_draining = true; ++ m2m_ctx->next_buf_last = true; ++ return; ++ } ++ ++ for (i = 0; i < vb->vb2_buf.num_planes; i++) ++ vb2_set_plane_payload(&vb->vb2_buf, i, 0); ++ vb->field = V4L2_FIELD_NONE; ++ ++ v4l2_m2m_last_buffer_done(m2m_ctx, vb); ++} ++ ++static void send_eos_event(struct vpu_instance *inst) ++{ ++ static const struct v4l2_event vpu_event_eos = { ++ .type = V4L2_EVENT_EOS ++ }; ++ ++ lockdep_assert_held(&inst->state_spinlock); ++ ++ v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_eos); ++ inst->eos = false; ++} ++ ++static int handle_dynamic_resolution_change(struct vpu_instance *inst) ++{ ++ struct v4l2_fh *fh = &inst->v4l2_fh; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ ++ static const struct v4l2_event vpu_event_src_ch = { ++ .type = V4L2_EVENT_SOURCE_CHANGE, ++ .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, ++ }; ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ struct dec_initial_info *initial_info = &inst->codec_info->dec_info.initial_info; ++ ++ lockdep_assert_held(&inst->state_spinlock); ++ ++ dev_dbg(inst->dev->dev, "%s: rd_ptr %pad", __func__, &initial_info->rd_ptr); ++ ++ dev_dbg(inst->dev->dev, "%s: width: %u height: %u profile: %u | minbuffer: %u\n", ++ __func__, initial_info->pic_width, initial_info->pic_height, ++ initial_info->profile, initial_info->min_frame_buffer_count); ++ ++ inst->needs_reallocation = true; ++ inst->fbc_buf_count = initial_info->min_frame_buffer_count + 1; ++ if (inst->fbc_buf_count != v4l2_m2m_num_dst_bufs_ready(m2m_ctx)) { ++ struct v4l2_ctrl *ctrl; ++ ++ ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE); ++ if (ctrl) ++ v4l2_ctrl_s_ctrl(ctrl, inst->fbc_buf_count); ++ } ++ ++ if (p_dec_info->initial_info_obtained) { ++ inst->conf_win.left = initial_info->pic_crop_rect.left; ++ inst->conf_win.top = initial_info->pic_crop_rect.top; ++ inst->conf_win.width = initial_info->pic_width - ++ initial_info->pic_crop_rect.left - initial_info->pic_crop_rect.right; ++ inst->conf_win.height = initial_info->pic_height - ++ initial_info->pic_crop_rect.top - initial_info->pic_crop_rect.bottom; ++ ++ wave5_update_pix_fmt(&inst->src_fmt, initial_info->pic_width, ++ initial_info->pic_height); ++ wave5_update_pix_fmt(&inst->dst_fmt, initial_info->pic_width, ++ initial_info->pic_height); ++ } ++ ++ v4l2_event_queue_fh(fh, &vpu_event_src_ch); ++ ++ return 0; ++} ++ ++static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct dec_output_info dec_info; ++ int ret; ++ struct vb2_v4l2_buffer *dec_buf = NULL; ++ struct vb2_v4l2_buffer *disp_buf = NULL; ++ struct vb2_queue *dst_vq = v4l2_m2m_get_dst_vq(m2m_ctx); ++ struct queue_status_info q_status; ++ ++ dev_dbg(inst->dev->dev, "%s: Fetch output info from firmware.", __func__); ++ ++ ret = wave5_vpu_dec_get_output_info(inst, &dec_info); ++ if (ret) { ++ dev_warn(inst->dev->dev, "%s: could not get output info.", __func__); ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++ return; ++ } ++ ++ dev_dbg(inst->dev->dev, "%s: rd_ptr %pad wr_ptr %pad", __func__, &dec_info.rd_ptr, ++ &dec_info.wr_ptr); ++ wave5_handle_src_buffer(inst, dec_info.rd_ptr); ++ ++ dev_dbg(inst->dev->dev, "%s: dec_info dec_idx %i disp_idx %i", __func__, ++ dec_info.index_frame_decoded, dec_info.index_frame_display); ++ ++ if (!vb2_is_streaming(dst_vq)) { ++ dev_dbg(inst->dev->dev, "%s: capture is not streaming..", __func__); ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++ return; ++ } ++ ++ /* Remove decoded buffer from the ready queue now that it has been ++ * decoded. ++ */ ++ if (dec_info.index_frame_decoded >= 0) { ++ struct vb2_buffer *vb = vb2_get_buffer(dst_vq, ++ dec_info.index_frame_decoded); ++ if (vb) { ++ dec_buf = to_vb2_v4l2_buffer(vb); ++ dec_buf->vb2_buf.timestamp = inst->timestamp; ++ } else { ++ dev_warn(inst->dev->dev, "%s: invalid decoded frame index %i", ++ __func__, dec_info.index_frame_decoded); ++ } ++ } ++ ++ if (dec_info.index_frame_display >= 0) { ++ disp_buf = v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, dec_info.index_frame_display); ++ if (!disp_buf) ++ dev_warn(inst->dev->dev, "%s: invalid display frame index %i", ++ __func__, dec_info.index_frame_display); ++ } ++ ++ /* If there is anything to display, do that now */ ++ if (disp_buf) { ++ struct vpu_dst_buffer *dst_vpu_buf = wave5_to_vpu_dst_buf(disp_buf); ++ ++ if (inst->dst_fmt.num_planes == 1) { ++ vb2_set_plane_payload(&disp_buf->vb2_buf, 0, ++ inst->dst_fmt.plane_fmt[0].sizeimage); ++ } else if (inst->dst_fmt.num_planes == 2) { ++ vb2_set_plane_payload(&disp_buf->vb2_buf, 0, ++ inst->dst_fmt.plane_fmt[0].sizeimage); ++ vb2_set_plane_payload(&disp_buf->vb2_buf, 1, ++ inst->dst_fmt.plane_fmt[1].sizeimage); ++ } else if (inst->dst_fmt.num_planes == 3) { ++ vb2_set_plane_payload(&disp_buf->vb2_buf, 0, ++ inst->dst_fmt.plane_fmt[0].sizeimage); ++ vb2_set_plane_payload(&disp_buf->vb2_buf, 1, ++ inst->dst_fmt.plane_fmt[1].sizeimage); ++ vb2_set_plane_payload(&disp_buf->vb2_buf, 2, ++ inst->dst_fmt.plane_fmt[2].sizeimage); ++ } ++ ++ /* TODO implement interlace support */ ++ disp_buf->field = V4L2_FIELD_NONE; ++ dst_vpu_buf->display = true; ++ v4l2_m2m_buf_done(disp_buf, VB2_BUF_STATE_DONE); ++ ++ dev_dbg(inst->dev->dev, "%s: frame_cycle %8u (payload %lu)\n", ++ __func__, dec_info.frame_cycle, ++ vb2_get_plane_payload(&disp_buf->vb2_buf, 0)); ++ } ++ ++ if ((dec_info.index_frame_display == DISPLAY_IDX_FLAG_SEQ_END || ++ dec_info.sequence_changed)) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&inst->state_spinlock, flags); ++ if (!v4l2_m2m_has_stopped(m2m_ctx)) { ++ switch_state(inst, VPU_INST_STATE_STOP); ++ ++ if (dec_info.sequence_changed) ++ handle_dynamic_resolution_change(inst); ++ else ++ send_eos_event(inst); ++ ++ flag_last_buffer_done(inst); ++ } ++ spin_unlock_irqrestore(&inst->state_spinlock, flags); ++ } ++ ++ /* ++ * During a resolution change and while draining, the firmware may flush ++ * the reorder queue regardless of having a matching decoding operation ++ * pending. Only terminate the job if there are no more IRQ coming. ++ */ ++ wave5_vpu_dec_give_command(inst, DEC_GET_QUEUE_STATUS, &q_status); ++ if (q_status.report_queue_count == 0 && ++ (q_status.instance_queue_count == 0 || dec_info.sequence_changed)) { ++ dev_dbg(inst->dev->dev, "%s: finishing job.\n", __func__); ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++ } ++} ++ ++static int wave5_vpu_dec_querycap(struct file *file, void *fh, struct v4l2_capability *cap) ++{ ++ strscpy(cap->driver, VPU_DEC_DRV_NAME, sizeof(cap->driver)); ++ strscpy(cap->card, VPU_DEC_DRV_NAME, sizeof(cap->card)); ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_enum_framesizes(struct file *f, void *fh, struct v4l2_frmsizeenum *fsize) ++{ ++ const struct vpu_format *vpu_fmt; ++ ++ if (fsize->index) ++ return -EINVAL; ++ ++ vpu_fmt = wave5_find_vpu_fmt(fsize->pixel_format, dec_fmt_list[VPU_FMT_TYPE_CODEC]); ++ if (!vpu_fmt) { ++ vpu_fmt = wave5_find_vpu_fmt(fsize->pixel_format, dec_fmt_list[VPU_FMT_TYPE_RAW]); ++ if (!vpu_fmt) ++ return -EINVAL; ++ } ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; ++ fsize->stepwise.min_width = vpu_fmt->min_width; ++ fsize->stepwise.max_width = vpu_fmt->max_width; ++ fsize->stepwise.step_width = 1; ++ fsize->stepwise.min_height = vpu_fmt->min_height; ++ fsize->stepwise.max_height = vpu_fmt->max_height; ++ fsize->stepwise.step_height = 1; ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_enum_fmt_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) ++{ ++ const struct vpu_format *vpu_fmt; ++ ++ vpu_fmt = wave5_find_vpu_fmt_by_idx(f->index, dec_fmt_list[VPU_FMT_TYPE_RAW]); ++ if (!vpu_fmt) ++ return -EINVAL; ++ ++ f->pixelformat = vpu_fmt->v4l2_pix_fmt; ++ f->flags = 0; ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ struct dec_info *p_dec_info = &inst->codec_info->dec_info; ++ const struct vpu_format *vpu_fmt; ++ int width, height; ++ ++ dev_dbg(inst->dev->dev, ++ "%s: fourcc: %u width: %u height: %u nm planes: %u colorspace: %u field: %u\n", ++ __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field); ++ ++ vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, dec_fmt_list[VPU_FMT_TYPE_RAW]); ++ if (!vpu_fmt) { ++ width = inst->dst_fmt.width; ++ height = inst->dst_fmt.height; ++ f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat; ++ f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes; ++ } else { ++ const struct v4l2_format_info *info = v4l2_format_info(vpu_fmt->v4l2_pix_fmt); ++ ++ width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width); ++ height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height); ++ f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt; ++ f->fmt.pix_mp.num_planes = info->mem_planes; ++ } ++ ++ if (p_dec_info->initial_info_obtained) { ++ width = inst->dst_fmt.width; ++ height = inst->dst_fmt.height; ++ } ++ ++ wave5_update_pix_fmt(&f->fmt.pix_mp, width, height); ++ f->fmt.pix_mp.flags = 0; ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ f->fmt.pix_mp.colorspace = inst->colorspace; ++ f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc; ++ f->fmt.pix_mp.quantization = inst->quantization; ++ f->fmt.pix_mp.xfer_func = inst->xfer_func; ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ int i, ret; ++ ++ dev_dbg(inst->dev->dev, ++ "%s: fourcc: %u width: %u height: %u num_planes: %u colorspace: %u field: %u\n", ++ __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field); ++ ++ ret = wave5_vpu_dec_try_fmt_cap(file, fh, f); ++ if (ret) ++ return ret; ++ ++ inst->dst_fmt.width = f->fmt.pix_mp.width; ++ inst->dst_fmt.height = f->fmt.pix_mp.height; ++ inst->dst_fmt.pixelformat = f->fmt.pix_mp.pixelformat; ++ inst->dst_fmt.field = f->fmt.pix_mp.field; ++ inst->dst_fmt.flags = f->fmt.pix_mp.flags; ++ inst->dst_fmt.num_planes = f->fmt.pix_mp.num_planes; ++ for (i = 0; i < inst->dst_fmt.num_planes; i++) { ++ inst->dst_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline; ++ inst->dst_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; ++ } ++ ++ if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12 || ++ inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12M) { ++ inst->cbcr_interleave = true; ++ inst->nv21 = false; ++ inst->output_format = FORMAT_420; ++ } else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV21 || ++ inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV21M) { ++ inst->cbcr_interleave = true; ++ inst->nv21 = true; ++ inst->output_format = FORMAT_420; ++ } else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV16 || ++ inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV16M) { ++ inst->cbcr_interleave = true; ++ inst->nv21 = false; ++ inst->output_format = FORMAT_422; ++ } else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV61 || ++ inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV61M) { ++ inst->cbcr_interleave = true; ++ inst->nv21 = true; ++ inst->output_format = FORMAT_422; ++ } else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_YUV422P || ++ inst->dst_fmt.pixelformat == V4L2_PIX_FMT_YUV422M) { ++ inst->cbcr_interleave = false; ++ inst->nv21 = false; ++ inst->output_format = FORMAT_422; ++ } else { ++ inst->cbcr_interleave = false; ++ inst->nv21 = false; ++ inst->output_format = FORMAT_420; ++ } ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ int i; ++ ++ f->fmt.pix_mp.width = inst->dst_fmt.width; ++ f->fmt.pix_mp.height = inst->dst_fmt.height; ++ f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat; ++ f->fmt.pix_mp.field = inst->dst_fmt.field; ++ f->fmt.pix_mp.flags = inst->dst_fmt.flags; ++ f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes; ++ for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { ++ f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->dst_fmt.plane_fmt[i].bytesperline; ++ f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->dst_fmt.plane_fmt[i].sizeimage; ++ } ++ ++ f->fmt.pix_mp.colorspace = inst->colorspace; ++ f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc; ++ f->fmt.pix_mp.quantization = inst->quantization; ++ f->fmt.pix_mp.xfer_func = inst->xfer_func; ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_enum_fmt_out(struct file *file, void *fh, struct v4l2_fmtdesc *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ const struct vpu_format *vpu_fmt; ++ ++ dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); ++ ++ vpu_fmt = wave5_find_vpu_fmt_by_idx(f->index, dec_fmt_list[VPU_FMT_TYPE_CODEC]); ++ if (!vpu_fmt) ++ return -EINVAL; ++ ++ f->pixelformat = vpu_fmt->v4l2_pix_fmt; ++ f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED; ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ const struct vpu_format *vpu_fmt; ++ ++ dev_dbg(inst->dev->dev, ++ "%s: fourcc: %u width: %u height: %u num_planes: %u colorspace: %u field: %u\n", ++ __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field); ++ ++ vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, dec_fmt_list[VPU_FMT_TYPE_CODEC]); ++ if (!vpu_fmt) { ++ f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat; ++ f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes; ++ wave5_update_pix_fmt(&f->fmt.pix_mp, inst->src_fmt.width, inst->src_fmt.height); ++ } else { ++ int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width); ++ int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height); ++ ++ f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt; ++ f->fmt.pix_mp.num_planes = 1; ++ wave5_update_pix_fmt(&f->fmt.pix_mp, width, height); ++ } ++ ++ f->fmt.pix_mp.flags = 0; ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ int i, ret; ++ ++ dev_dbg(inst->dev->dev, ++ "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", ++ __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field); ++ ++ ret = wave5_vpu_dec_try_fmt_out(file, fh, f); ++ if (ret) ++ return ret; ++ ++ inst->std = wave5_to_vpu_std(f->fmt.pix_mp.pixelformat, inst->type); ++ if (inst->std == STD_UNKNOWN) { ++ dev_warn(inst->dev->dev, "unsupported pixelformat: %.4s\n", ++ (char *)&f->fmt.pix_mp.pixelformat); ++ return -EINVAL; ++ } ++ ++ inst->src_fmt.width = f->fmt.pix_mp.width; ++ inst->src_fmt.height = f->fmt.pix_mp.height; ++ inst->src_fmt.pixelformat = f->fmt.pix_mp.pixelformat; ++ inst->src_fmt.field = f->fmt.pix_mp.field; ++ inst->src_fmt.flags = f->fmt.pix_mp.flags; ++ inst->src_fmt.num_planes = f->fmt.pix_mp.num_planes; ++ for (i = 0; i < inst->src_fmt.num_planes; i++) { ++ inst->src_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline; ++ inst->src_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; ++ } ++ ++ inst->colorspace = f->fmt.pix_mp.colorspace; ++ inst->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; ++ inst->quantization = f->fmt.pix_mp.quantization; ++ inst->xfer_func = f->fmt.pix_mp.xfer_func; ++ ++ wave5_update_pix_fmt(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height); ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ ++ dev_dbg(inst->dev->dev, "%s: type: %u | target: %u\n", __func__, s->type, s->target); ++ ++ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ switch (s->target) { ++ case V4L2_SEL_TGT_COMPOSE_BOUNDS: ++ case V4L2_SEL_TGT_COMPOSE_PADDED: ++ s->r.left = 0; ++ s->r.top = 0; ++ s->r.width = inst->dst_fmt.width; ++ s->r.height = inst->dst_fmt.height; ++ break; ++ case V4L2_SEL_TGT_COMPOSE: ++ case V4L2_SEL_TGT_COMPOSE_DEFAULT: ++ s->r.left = 0; ++ s->r.top = 0; ++ if (inst->state > VPU_INST_STATE_OPEN) { ++ s->r = inst->conf_win; ++ } else { ++ s->r.width = inst->src_fmt.width; ++ s->r.height = inst->src_fmt.height; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_s_selection(struct file *file, void *fh, struct v4l2_selection *s) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ ++ if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) ++ return -EINVAL; ++ ++ if (s->target != V4L2_SEL_TGT_COMPOSE) ++ return -EINVAL; ++ ++ dev_dbg(inst->dev->dev, "V4L2_SEL_TGT_COMPOSE w: %u h: %u\n", ++ s->r.width, s->r.height); ++ ++ s->r.left = 0; ++ s->r.top = 0; ++ s->r.width = inst->dst_fmt.width; ++ s->r.height = inst->dst_fmt.height; ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_stop(struct vpu_instance *inst) ++{ ++ int ret = 0; ++ unsigned long flags; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ ++ spin_lock_irqsave(&inst->state_spinlock, flags); ++ ++ if (m2m_ctx->is_draining) { ++ ret = -EBUSY; ++ goto unlock_and_return; ++ } ++ ++ if (inst->state != VPU_INST_STATE_NONE) { ++ /* ++ * Temporarily release the state_spinlock so that subsequent ++ * calls do not block on a mutex while inside this spinlock. ++ */ ++ spin_unlock_irqrestore(&inst->state_spinlock, flags); ++ ret = wave5_vpu_dec_set_eos_on_firmware(inst); ++ if (ret) ++ return ret; ++ ++ spin_lock_irqsave(&inst->state_spinlock, flags); ++ /* ++ * TODO eliminate this check by using a separate check for ++ * draining triggered by a resolution change. ++ */ ++ if (m2m_ctx->is_draining) { ++ ret = -EBUSY; ++ goto unlock_and_return; ++ } ++ } ++ ++ /* ++ * Used to remember the EOS state after the streamoff/on transition on ++ * the capture queue. ++ */ ++ inst->eos = true; ++ ++ if (m2m_ctx->has_stopped) ++ goto unlock_and_return; ++ ++ m2m_ctx->last_src_buf = v4l2_m2m_last_src_buf(m2m_ctx); ++ m2m_ctx->is_draining = true; ++ ++ /* ++ * Deferred to device run in case it wasn't in the ring buffer ++ * yet. In other case, we have to send the EOS signal to the ++ * firmware so that any pending PIC_RUN ends without new ++ * bitstream buffer. ++ */ ++ if (m2m_ctx->last_src_buf) ++ goto unlock_and_return; ++ ++ if (inst->state == VPU_INST_STATE_NONE) { ++ send_eos_event(inst); ++ flag_last_buffer_done(inst); ++ } ++ ++unlock_and_return: ++ spin_unlock_irqrestore(&inst->state_spinlock, flags); ++ return ret; ++} ++ ++static int wave5_vpu_dec_start(struct vpu_instance *inst) ++{ ++ int ret = 0; ++ unsigned long flags; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct vb2_queue *dst_vq = v4l2_m2m_get_dst_vq(m2m_ctx); ++ ++ spin_lock_irqsave(&inst->state_spinlock, flags); ++ ++ if (m2m_ctx->is_draining) { ++ ret = -EBUSY; ++ goto unlock_and_return; ++ } ++ ++ if (m2m_ctx->has_stopped) ++ m2m_ctx->has_stopped = false; ++ ++ vb2_clear_last_buffer_dequeued(dst_vq); ++ inst->eos = false; ++ ++unlock_and_return: ++ spin_unlock_irqrestore(&inst->state_spinlock, flags); ++ return ret; ++} ++ ++static int wave5_vpu_dec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dc) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ int ret; ++ ++ dev_dbg(inst->dev->dev, "decoder command: %u\n", dc->cmd); ++ ++ ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc); ++ if (ret) ++ return ret; ++ ++ switch (dc->cmd) { ++ case V4L2_DEC_CMD_STOP: ++ ret = wave5_vpu_dec_stop(inst); ++ /* Just in case we don't have anything to decode anymore */ ++ v4l2_m2m_try_schedule(m2m_ctx); ++ break; ++ case V4L2_DEC_CMD_START: ++ ret = wave5_vpu_dec_start(inst); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static const struct v4l2_ioctl_ops wave5_vpu_dec_ioctl_ops = { ++ .vidioc_querycap = wave5_vpu_dec_querycap, ++ .vidioc_enum_framesizes = wave5_vpu_dec_enum_framesizes, ++ ++ .vidioc_enum_fmt_vid_cap = wave5_vpu_dec_enum_fmt_cap, ++ .vidioc_s_fmt_vid_cap_mplane = wave5_vpu_dec_s_fmt_cap, ++ .vidioc_g_fmt_vid_cap_mplane = wave5_vpu_dec_g_fmt_cap, ++ .vidioc_try_fmt_vid_cap_mplane = wave5_vpu_dec_try_fmt_cap, ++ ++ .vidioc_enum_fmt_vid_out = wave5_vpu_dec_enum_fmt_out, ++ .vidioc_s_fmt_vid_out_mplane = wave5_vpu_dec_s_fmt_out, ++ .vidioc_g_fmt_vid_out_mplane = wave5_vpu_g_fmt_out, ++ .vidioc_try_fmt_vid_out_mplane = wave5_vpu_dec_try_fmt_out, ++ ++ .vidioc_g_selection = wave5_vpu_dec_g_selection, ++ .vidioc_s_selection = wave5_vpu_dec_s_selection, ++ ++ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, ++ /* ++ * Firmware does not support CREATE_BUFS for CAPTURE queue. Since ++ * there is no immediate use-case for supporting CREATE_BUFS on ++ * just the OUTPUT queue, disable CREATE_BUFS altogether. ++ */ ++ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, ++ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, ++ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, ++ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, ++ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, ++ .vidioc_streamon = v4l2_m2m_ioctl_streamon, ++ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, ++ ++ .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd, ++ .vidioc_decoder_cmd = wave5_vpu_dec_decoder_cmd, ++ ++ .vidioc_subscribe_event = wave5_vpu_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, ++ unsigned int *num_planes, unsigned int sizes[], ++ struct device *alloc_devs[]) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ struct v4l2_pix_format_mplane inst_format = ++ (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->dst_fmt; ++ ++ dev_dbg(inst->dev->dev, "%s: num_buffers: %u | num_planes: %u | type: %u\n", __func__, ++ *num_buffers, *num_planes, q->type); ++ ++ *num_planes = inst_format.num_planes; ++ ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ++ sizes[0] = inst_format.plane_fmt[0].sizeimage; ++ dev_dbg(inst->dev->dev, "%s: size[0]: %u\n", __func__, sizes[0]); ++ } else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { ++ if (*num_buffers < inst->fbc_buf_count) ++ *num_buffers = inst->fbc_buf_count; ++ ++ if (*num_planes == 1) { ++ if (inst->output_format == FORMAT_422) ++ sizes[0] = inst_format.width * inst_format.height * 2; ++ else ++ sizes[0] = inst_format.width * inst_format.height * 3 / 2; ++ dev_dbg(inst->dev->dev, "%s: size[0]: %u\n", __func__, sizes[0]); ++ } else if (*num_planes == 2) { ++ sizes[0] = inst_format.width * inst_format.height; ++ if (inst->output_format == FORMAT_422) ++ sizes[1] = inst_format.width * inst_format.height; ++ else ++ sizes[1] = inst_format.width * inst_format.height / 2; ++ dev_dbg(inst->dev->dev, "%s: size[0]: %u | size[1]: %u\n", ++ __func__, sizes[0], sizes[1]); ++ } else if (*num_planes == 3) { ++ sizes[0] = inst_format.width * inst_format.height; ++ if (inst->output_format == FORMAT_422) { ++ sizes[1] = inst_format.width * inst_format.height / 2; ++ sizes[2] = inst_format.width * inst_format.height / 2; ++ } else { ++ sizes[1] = inst_format.width * inst_format.height / 4; ++ sizes[2] = inst_format.width * inst_format.height / 4; ++ } ++ dev_dbg(inst->dev->dev, "%s: size[0]: %u | size[1]: %u | size[2]: %u\n", ++ __func__, sizes[0], sizes[1], sizes[2]); ++ } ++ } ++ ++ return 0; ++} ++ ++static int wave5_prepare_fb(struct vpu_instance *inst) ++{ ++ int linear_num; ++ int non_linear_num; ++ int fb_stride = 0, fb_height = 0; ++ int luma_size, chroma_size; ++ int ret, i; ++ struct v4l2_m2m_buffer *buf, *n; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ ++ linear_num = v4l2_m2m_num_dst_bufs_ready(m2m_ctx); ++ non_linear_num = inst->fbc_buf_count; ++ ++ for (i = 0; i < non_linear_num; i++) { ++ struct frame_buffer *frame = &inst->frame_buf[i]; ++ struct vpu_buf *vframe = &inst->frame_vbuf[i]; ++ ++ fb_stride = inst->dst_fmt.width; ++ fb_height = ALIGN(inst->dst_fmt.height, 32); ++ luma_size = fb_stride * fb_height; ++ ++ chroma_size = ALIGN(fb_stride / 2, 16) * fb_height; ++ ++ if (vframe->size == (luma_size + chroma_size)) ++ continue; ++ ++ if (vframe->size) ++ wave5_vpu_dec_reset_framebuffer(inst, i); ++ ++ vframe->size = luma_size + chroma_size; ++ ret = wave5_vdi_allocate_dma_memory(inst->dev, vframe); ++ if (ret) { ++ dev_dbg(inst->dev->dev, ++ "%s: Allocating FBC buf of size %zu, fail: %d\n", ++ __func__, vframe->size, ret); ++ return ret; ++ } ++ ++ frame->buf_y = vframe->daddr; ++ frame->buf_cb = vframe->daddr + luma_size; ++ frame->buf_cr = (dma_addr_t)-1; ++ frame->size = vframe->size; ++ frame->width = inst->src_fmt.width; ++ frame->stride = fb_stride; ++ frame->map_type = COMPRESSED_FRAME_MAP; ++ frame->update_fb_info = true; ++ } ++ /* In case the count has reduced, clean up leftover framebuffer memory */ ++ for (i = non_linear_num; i < MAX_REG_FRAME; i++) { ++ ret = wave5_vpu_dec_reset_framebuffer(inst, i); ++ if (ret) ++ break; ++ } ++ ++ for (i = 0; i < linear_num; i++) { ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct vb2_queue *dst_vq = v4l2_m2m_get_dst_vq(m2m_ctx); ++ struct vb2_buffer *vb = vb2_get_buffer(dst_vq, i); ++ struct frame_buffer *frame = &inst->frame_buf[non_linear_num + i]; ++ dma_addr_t buf_addr_y = 0, buf_addr_cb = 0, buf_addr_cr = 0; ++ u32 buf_size = 0; ++ u32 fb_stride = inst->dst_fmt.width; ++ u32 luma_size = fb_stride * inst->dst_fmt.height; ++ u32 chroma_size; ++ ++ if (inst->output_format == FORMAT_422) ++ chroma_size = fb_stride * inst->dst_fmt.height / 2; ++ else ++ chroma_size = fb_stride * inst->dst_fmt.height / 4; ++ ++ if (inst->dst_fmt.num_planes == 1) { ++ buf_size = vb2_plane_size(vb, 0); ++ buf_addr_y = vb2_dma_contig_plane_dma_addr(vb, 0); ++ buf_addr_cb = buf_addr_y + luma_size; ++ buf_addr_cr = buf_addr_cb + chroma_size; ++ } else if (inst->dst_fmt.num_planes == 2) { ++ buf_size = vb2_plane_size(vb, 0) + ++ vb2_plane_size(vb, 1); ++ buf_addr_y = vb2_dma_contig_plane_dma_addr(vb, 0); ++ buf_addr_cb = vb2_dma_contig_plane_dma_addr(vb, 1); ++ buf_addr_cr = buf_addr_cb + chroma_size; ++ } else if (inst->dst_fmt.num_planes == 3) { ++ buf_size = vb2_plane_size(vb, 0) + ++ vb2_plane_size(vb, 1) + ++ vb2_plane_size(vb, 2); ++ buf_addr_y = vb2_dma_contig_plane_dma_addr(vb, 0); ++ buf_addr_cb = vb2_dma_contig_plane_dma_addr(vb, 1); ++ buf_addr_cr = vb2_dma_contig_plane_dma_addr(vb, 2); ++ } ++ ++ frame->buf_y = buf_addr_y; ++ frame->buf_cb = buf_addr_cb; ++ frame->buf_cr = buf_addr_cr; ++ frame->size = buf_size; ++ frame->width = inst->src_fmt.width; ++ frame->stride = fb_stride; ++ frame->map_type = LINEAR_FRAME_MAP; ++ frame->update_fb_info = true; ++ } ++ ++ ret = wave5_vpu_dec_register_frame_buffer_ex(inst, non_linear_num, linear_num, ++ fb_stride, inst->dst_fmt.height); ++ if (ret) { ++ dev_dbg(inst->dev->dev, "%s: vpu_dec_register_frame_buffer_ex fail: %d", ++ __func__, ret); ++ return ret; ++ } ++ ++ /* ++ * Mark all frame buffers as out of display, to avoid using them before ++ * the application have them queued. ++ */ ++ for (i = 0; i < v4l2_m2m_num_dst_bufs_ready(m2m_ctx); i++) { ++ ret = wave5_vpu_dec_set_disp_flag(inst, i); ++ if (ret) { ++ dev_dbg(inst->dev->dev, ++ "%s: Setting display flag of buf index: %u, fail: %d\n", ++ __func__, i, ret); ++ } ++ } ++ ++ v4l2_m2m_for_each_dst_buf_safe(m2m_ctx, buf, n) { ++ struct vb2_v4l2_buffer *vbuf = &buf->vb; ++ ++ ret = wave5_vpu_dec_clr_disp_flag(inst, vbuf->vb2_buf.index); ++ if (ret) ++ dev_dbg(inst->dev->dev, ++ "%s: Clearing display flag of buf index: %u, fail: %d\n", ++ __func__, i, ret); ++ } ++ ++ return 0; ++} ++ ++static int write_to_ringbuffer(struct vpu_instance *inst, void *buffer, size_t buffer_size, ++ struct vpu_buf *ring_buffer, dma_addr_t wr_ptr) ++{ ++ size_t size; ++ size_t offset = wr_ptr - ring_buffer->daddr; ++ int ret; ++ ++ if (wr_ptr + buffer_size > ring_buffer->daddr + ring_buffer->size) { ++ size = ring_buffer->daddr + ring_buffer->size - wr_ptr; ++ ret = wave5_vdi_write_memory(inst->dev, ring_buffer, offset, (u8 *)buffer, size); ++ if (ret < 0) ++ return ret; ++ ++ ret = wave5_vdi_write_memory(inst->dev, ring_buffer, 0, (u8 *)buffer + size, ++ buffer_size - size); ++ if (ret < 0) ++ return ret; ++ } else { ++ ret = wave5_vdi_write_memory(inst->dev, ring_buffer, offset, (u8 *)buffer, ++ buffer_size); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int fill_ringbuffer(struct vpu_instance *inst) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct v4l2_m2m_buffer *buf, *n; ++ int ret; ++ ++ if (m2m_ctx->last_src_buf) { ++ struct vpu_src_buffer *vpu_buf = wave5_to_vpu_src_buf(m2m_ctx->last_src_buf); ++ ++ if (vpu_buf->consumed) { ++ dev_dbg(inst->dev->dev, "last src buffer already written\n"); ++ return 0; ++ } ++ } ++ ++ v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buf, n) { ++ struct vb2_v4l2_buffer *vbuf = &buf->vb; ++ struct vpu_src_buffer *vpu_buf = wave5_to_vpu_src_buf(vbuf); ++ struct vpu_buf *ring_buffer = &inst->bitstream_vbuf; ++ size_t src_size = vb2_get_plane_payload(&vbuf->vb2_buf, 0); ++ void *src_buf = vb2_plane_vaddr(&vbuf->vb2_buf, 0); ++ dma_addr_t rd_ptr = 0; ++ dma_addr_t wr_ptr = 0; ++ size_t remain_size = 0; ++ ++ if (vpu_buf->consumed) { ++ dev_dbg(inst->dev->dev, "already copied src buf (%u) to the ring buffer\n", ++ vbuf->vb2_buf.index); ++ continue; ++ } ++ ++ if (!src_buf) { ++ dev_dbg(inst->dev->dev, ++ "%s: Acquiring kernel pointer to src buf (%u), fail\n", ++ __func__, vbuf->vb2_buf.index); ++ break; ++ } ++ ++ ret = wave5_vpu_dec_get_bitstream_buffer(inst, &rd_ptr, &wr_ptr, &remain_size); ++ if (ret) { ++ /* Unable to acquire the mutex */ ++ dev_err(inst->dev->dev, "Getting the bitstream buffer, fail: %d\n", ++ ret); ++ return ret; ++ } ++ ++ dev_dbg(inst->dev->dev, "%s: rd_ptr %pad wr_ptr %pad", __func__, &rd_ptr, &wr_ptr); ++ ++ if (remain_size < src_size) { ++ dev_dbg(inst->dev->dev, ++ "%s: remaining size: %zu < source size: %zu for src buf (%u)\n", ++ __func__, remain_size, src_size, vbuf->vb2_buf.index); ++ break; ++ } ++ ++ ret = write_to_ringbuffer(inst, src_buf, src_size, ring_buffer, wr_ptr); ++ if (ret) { ++ dev_err(inst->dev->dev, "Write src buf (%u) to ring buffer, fail: %d\n", ++ vbuf->vb2_buf.index, ret); ++ return ret; ++ } ++ ++ ret = wave5_vpu_dec_update_bitstream_buffer(inst, src_size); ++ if (ret) { ++ dev_dbg(inst->dev->dev, ++ "update_bitstream_buffer fail: %d for src buf (%u)\n", ++ ret, vbuf->vb2_buf.index); ++ break; ++ } ++ ++ vpu_buf->consumed = true; ++ ++ /* Don't write buffers passed the last one while draining. */ ++ if (v4l2_m2m_is_last_draining_src_buf(m2m_ctx, vbuf)) { ++ dev_dbg(inst->dev->dev, "last src buffer written to the ring bufferur\n"); ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static void wave5_vpu_dec_buf_queue_src(struct vb2_buffer *vb) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct vpu_src_buffer *vpu_buf = wave5_to_vpu_src_buf(vbuf); ++ ++ vpu_buf->consumed = false; ++ vbuf->sequence = inst->queued_src_buf_num++; ++ ++ v4l2_m2m_buf_queue(m2m_ctx, vbuf); ++} ++ ++static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ ++ vbuf->sequence = inst->queued_dst_buf_num++; ++ ++ if (inst->state == VPU_INST_STATE_PIC_RUN) { ++ struct vpu_dst_buffer *vpu_buf = wave5_to_vpu_dst_buf(vbuf); ++ int ret; ++ ++ /* ++ * The buffer is already registered just clear the display flag ++ * to let the firmware know it can be used. ++ */ ++ vpu_buf->display = false; ++ ret = wave5_vpu_dec_clr_disp_flag(inst, vb->index); ++ if (ret) { ++ dev_dbg(inst->dev->dev, ++ "%s: Clearing the display flag of buffer index: %u, fail: %d\n", ++ __func__, vb->index, ret); ++ } ++ } ++ ++ if (vb2_is_streaming(vb->vb2_queue) && v4l2_m2m_dst_buf_is_last(m2m_ctx)) { ++ unsigned int i; ++ ++ for (i = 0; i < vb->num_planes; i++) ++ vb2_set_plane_payload(vb, i, 0); ++ ++ vbuf->field = V4L2_FIELD_NONE; ++ ++ send_eos_event(inst); ++ v4l2_m2m_last_buffer_done(m2m_ctx, vbuf); ++ } else { ++ v4l2_m2m_buf_queue(m2m_ctx, vbuf); ++ } ++} ++ ++static void wave5_vpu_dec_buf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue); ++ ++ dev_dbg(inst->dev->dev, "%s: type: %4u index: %4u size: ([0]=%4lu, [1]=%4lu, [2]=%4lu)\n", ++ __func__, vb->type, vb->index, vb2_plane_size(&vbuf->vb2_buf, 0), ++ vb2_plane_size(&vbuf->vb2_buf, 1), vb2_plane_size(&vbuf->vb2_buf, 2)); ++ ++ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ++ wave5_vpu_dec_buf_queue_src(vb); ++ else if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) ++ wave5_vpu_dec_buf_queue_dst(vb); ++} ++ ++static int wave5_vpu_dec_allocate_ring_buffer(struct vpu_instance *inst) ++{ ++ int ret; ++ struct vpu_buf *ring_buffer = &inst->bitstream_vbuf; ++ ++ ring_buffer->size = ALIGN(inst->src_fmt.plane_fmt[0].sizeimage, 1024) * 4; ++ ret = wave5_vdi_allocate_dma_memory(inst->dev, ring_buffer); ++ if (ret) { ++ dev_dbg(inst->dev->dev, "%s: allocate ring buffer of size %zu fail: %d\n", ++ __func__, ring_buffer->size, ret); ++ return ret; ++ } ++ ++ inst->last_rd_ptr = ring_buffer->daddr; ++ ++ return 0; ++} ++ ++static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ int ret = 0; ++ ++ dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type); ++ ++ v4l2_m2m_update_start_streaming_state(m2m_ctx, q); ++ ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && inst->state == VPU_INST_STATE_NONE) { ++ struct dec_open_param open_param; ++ ++ memset(&open_param, 0, sizeof(struct dec_open_param)); ++ ++ ret = wave5_vpu_dec_allocate_ring_buffer(inst); ++ if (ret) ++ goto return_buffers; ++ ++ open_param.bitstream_buffer = inst->bitstream_vbuf.daddr; ++ open_param.bitstream_buffer_size = inst->bitstream_vbuf.size; ++ ++ ret = wave5_vpu_dec_open(inst, &open_param); ++ if (ret) { ++ dev_dbg(inst->dev->dev, "%s: decoder opening, fail: %d\n", ++ __func__, ret); ++ goto free_bitstream_vbuf; ++ } ++ ++ ret = switch_state(inst, VPU_INST_STATE_OPEN); ++ if (ret) ++ goto free_bitstream_vbuf; ++ } else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { ++ struct dec_initial_info *initial_info = ++ &inst->codec_info->dec_info.initial_info; ++ ++ if (inst->state == VPU_INST_STATE_STOP) ++ ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ); ++ if (ret) ++ goto return_buffers; ++ ++ if (inst->state == VPU_INST_STATE_INIT_SEQ) { ++ if (initial_info->luma_bitdepth != 8) { ++ dev_info(inst->dev->dev, "%s: no support for %d bit depth", ++ __func__, initial_info->luma_bitdepth); ++ ret = -EINVAL; ++ goto return_buffers; ++ } ++ } ++ } ++ ++ return ret; ++ ++free_bitstream_vbuf: ++ wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf); ++return_buffers: ++ wave5_return_bufs(q, VB2_BUF_STATE_QUEUED); ++ return ret; ++} ++ ++static int streamoff_output(struct vb2_queue *q) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct vb2_v4l2_buffer *buf; ++ int ret; ++ dma_addr_t new_rd_ptr; ++ ++ while ((buf = v4l2_m2m_src_buf_remove(m2m_ctx))) { ++ dev_dbg(inst->dev->dev, "%s: (Multiplanar) buf type %4u | index %4u\n", ++ __func__, buf->vb2_buf.type, buf->vb2_buf.index); ++ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); ++ } ++ ++ ret = wave5_vpu_flush_instance(inst); ++ if (ret) ++ return ret; ++ ++ /* Reset the ring buffer information */ ++ new_rd_ptr = wave5_vpu_dec_get_rd_ptr(inst); ++ inst->last_rd_ptr = new_rd_ptr; ++ inst->codec_info->dec_info.stream_rd_ptr = new_rd_ptr; ++ inst->codec_info->dec_info.stream_wr_ptr = new_rd_ptr; ++ ++ if (v4l2_m2m_has_stopped(m2m_ctx)) ++ send_eos_event(inst); ++ ++ /* streamoff on output cancels any draining operation */ ++ inst->eos = false; ++ ++ return 0; ++} ++ ++static int streamoff_capture(struct vb2_queue *q) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct vb2_v4l2_buffer *buf; ++ unsigned int i; ++ int ret = 0; ++ ++ for (i = 0; i < v4l2_m2m_num_dst_bufs_ready(m2m_ctx); i++) { ++ ret = wave5_vpu_dec_set_disp_flag(inst, i); ++ if (ret) ++ dev_dbg(inst->dev->dev, ++ "%s: Setting display flag of buf index: %u, fail: %d\n", ++ __func__, i, ret); ++ } ++ ++ while ((buf = v4l2_m2m_dst_buf_remove(m2m_ctx))) { ++ u32 plane; ++ ++ dev_dbg(inst->dev->dev, "%s: buf type %4u | index %4u\n", ++ __func__, buf->vb2_buf.type, buf->vb2_buf.index); ++ ++ for (plane = 0; plane < inst->dst_fmt.num_planes; plane++) ++ vb2_set_plane_payload(&buf->vb2_buf, plane, 0); ++ ++ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); ++ } ++ ++ if (inst->needs_reallocation) { ++ wave5_vpu_dec_give_command(inst, DEC_RESET_FRAMEBUF_INFO, NULL); ++ inst->needs_reallocation = false; ++ } ++ ++ if (v4l2_m2m_has_stopped(m2m_ctx)) { ++ ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ bool check_cmd = TRUE; ++ ++ dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type); ++ ++ while (check_cmd) { ++ struct queue_status_info q_status; ++ struct dec_output_info dec_output_info; ++ ++ wave5_vpu_dec_give_command(inst, DEC_GET_QUEUE_STATUS, &q_status); ++ ++ if (q_status.report_queue_count == 0) ++ break; ++ ++ if (wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT) < 0) ++ break; ++ ++ if (wave5_vpu_dec_get_output_info(inst, &dec_output_info)) ++ dev_dbg(inst->dev->dev, "Getting decoding results from fw, fail\n"); ++ } ++ ++ v4l2_m2m_update_stop_streaming_state(m2m_ctx, q); ++ ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ++ streamoff_output(q); ++ else ++ streamoff_capture(q); ++} ++ ++static const struct vb2_ops wave5_vpu_dec_vb2_ops = { ++ .queue_setup = wave5_vpu_dec_queue_setup, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++ .buf_queue = wave5_vpu_dec_buf_queue, ++ .start_streaming = wave5_vpu_dec_start_streaming, ++ .stop_streaming = wave5_vpu_dec_stop_streaming, ++}; ++ ++static void wave5_set_default_format(struct v4l2_pix_format_mplane *src_fmt, ++ struct v4l2_pix_format_mplane *dst_fmt) ++{ ++ unsigned int dst_pix_fmt = dec_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt; ++ const struct v4l2_format_info *dst_fmt_info = v4l2_format_info(dst_pix_fmt); ++ ++ src_fmt->pixelformat = dec_fmt_list[VPU_FMT_TYPE_CODEC][0].v4l2_pix_fmt; ++ src_fmt->field = V4L2_FIELD_NONE; ++ src_fmt->flags = 0; ++ src_fmt->num_planes = 1; ++ wave5_update_pix_fmt(src_fmt, 720, 480); ++ ++ dst_fmt->pixelformat = dst_pix_fmt; ++ dst_fmt->field = V4L2_FIELD_NONE; ++ dst_fmt->flags = 0; ++ dst_fmt->num_planes = dst_fmt_info->mem_planes; ++ wave5_update_pix_fmt(dst_fmt, 736, 480); ++} ++ ++static int wave5_vpu_dec_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) ++{ ++ return wave5_vpu_queue_init(priv, src_vq, dst_vq, &wave5_vpu_dec_vb2_ops); ++} ++ ++static const struct vpu_instance_ops wave5_vpu_dec_inst_ops = { ++ .finish_process = wave5_vpu_dec_finish_decode, ++}; ++ ++static int initialize_sequence(struct vpu_instance *inst) ++{ ++ struct dec_initial_info initial_info; ++ int ret = 0; ++ ++ memset(&initial_info, 0, sizeof(struct dec_initial_info)); ++ ++ ret = wave5_vpu_dec_issue_seq_init(inst); ++ if (ret) { ++ dev_dbg(inst->dev->dev, "%s: wave5_vpu_dec_issue_seq_init, fail: %d\n", ++ __func__, ret); ++ return ret; ++ } ++ ++ if (wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT) < 0) ++ dev_dbg(inst->dev->dev, "%s: failed to call vpu_wait_interrupt()\n", __func__); ++ ++ ret = wave5_vpu_dec_complete_seq_init(inst, &initial_info); ++ if (ret) { ++ dev_dbg(inst->dev->dev, "%s: vpu_dec_complete_seq_init, fail: %d, reason: %u\n", ++ __func__, ret, initial_info.seq_init_err_reason); ++ wave5_handle_src_buffer(inst, initial_info.rd_ptr); ++ return ret; ++ } ++ ++ handle_dynamic_resolution_change(inst); ++ ++ return 0; ++} ++ ++static bool wave5_is_draining_or_eos(struct vpu_instance *inst) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ ++ lockdep_assert_held(&inst->state_spinlock); ++ return m2m_ctx->is_draining || inst->eos; ++} ++ ++static void wave5_vpu_dec_device_run(void *priv) ++{ ++ struct vpu_instance *inst = priv; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct queue_status_info q_status; ++ u32 fail_res = 0; ++ int ret = 0; ++ ++ dev_dbg(inst->dev->dev, "%s: Fill the ring buffer with new bitstream data", __func__); ++ ++ ret = fill_ringbuffer(inst); ++ if (ret) { ++ dev_warn(inst->dev->dev, "Filling ring buffer failed\n"); ++ goto finish_job_and_return; ++ } ++ ++ switch (inst->state) { ++ case VPU_INST_STATE_OPEN: ++ ret = initialize_sequence(inst); ++ if (ret) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&inst->state_spinlock, flags); ++ if (wave5_is_draining_or_eos(inst) && ++ wave5_last_src_buffer_consumed(m2m_ctx)) { ++ struct vb2_queue *dst_vq = v4l2_m2m_get_dst_vq(m2m_ctx); ++ ++ switch_state(inst, VPU_INST_STATE_STOP); ++ ++ if (vb2_is_streaming(dst_vq)) ++ send_eos_event(inst); ++ else ++ handle_dynamic_resolution_change(inst); ++ ++ flag_last_buffer_done(inst); ++ } ++ spin_unlock_irqrestore(&inst->state_spinlock, flags); ++ } else { ++ switch_state(inst, VPU_INST_STATE_INIT_SEQ); ++ } ++ ++ break; ++ ++ case VPU_INST_STATE_INIT_SEQ: ++ /* ++ * Do this early, preparing the fb can trigger an IRQ before ++ * we had a chance to switch, which leads to an invalid state ++ * change. ++ */ ++ switch_state(inst, VPU_INST_STATE_PIC_RUN); ++ ++ /* ++ * During DRC, the picture decoding remains pending, so just leave the job ++ * active until this decode operation completes. ++ */ ++ wave5_vpu_dec_give_command(inst, DEC_GET_QUEUE_STATUS, &q_status); ++ ++ /* ++ * The sequence must be analyzed first to calculate the proper ++ * size of the auxiliary buffers. ++ */ ++ ret = wave5_prepare_fb(inst); ++ if (ret) { ++ dev_warn(inst->dev->dev, "Framebuffer preparation, fail: %d\n", ret); ++ switch_state(inst, VPU_INST_STATE_STOP); ++ break; ++ } ++ ++ if (q_status.instance_queue_count) { ++ dev_dbg(inst->dev->dev, "%s: leave with active job", __func__); ++ return; ++ } ++ ++ fallthrough; ++ case VPU_INST_STATE_PIC_RUN: ++ ret = start_decode(inst, &fail_res); ++ if (ret) { ++ dev_err(inst->dev->dev, ++ "Frame decoding on m2m context (%p), fail: %d (result: %d)\n", ++ m2m_ctx, ret, fail_res); ++ break; ++ } ++ /* Return so that we leave this job active */ ++ dev_dbg(inst->dev->dev, "%s: leave with active job", __func__); ++ return; ++ default: ++ WARN(1, "Execution of a job in state %s illegal.\n", state_to_str(inst->state)); ++ break; ++ } ++ ++finish_job_and_return: ++ dev_dbg(inst->dev->dev, "%s: leave and finish job", __func__); ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++} ++ ++static void wave5_vpu_dec_job_abort(void *priv) ++{ ++ struct vpu_instance *inst = priv; ++ int ret; ++ ++ ret = switch_state(inst, VPU_INST_STATE_STOP); ++ if (ret) ++ return; ++ ++ ret = wave5_vpu_dec_set_eos_on_firmware(inst); ++ if (ret) ++ dev_warn(inst->dev->dev, ++ "Setting EOS for the bitstream, fail: %d\n", ret); ++} ++ ++static int wave5_vpu_dec_job_ready(void *priv) ++{ ++ struct vpu_instance *inst = priv; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ unsigned long flags; ++ int ret = 0; ++ ++ spin_lock_irqsave(&inst->state_spinlock, flags); ++ ++ switch (inst->state) { ++ case VPU_INST_STATE_NONE: ++ dev_dbg(inst->dev->dev, "Decoder must be open to start queueing M2M jobs!\n"); ++ break; ++ case VPU_INST_STATE_OPEN: ++ if (wave5_is_draining_or_eos(inst) || !v4l2_m2m_has_stopped(m2m_ctx) || ++ v4l2_m2m_num_src_bufs_ready(m2m_ctx) > 0) { ++ ret = 1; ++ break; ++ } ++ ++ dev_dbg(inst->dev->dev, ++ "Decoder must be draining or >= 1 OUTPUT queue buffer must be queued!\n"); ++ break; ++ case VPU_INST_STATE_INIT_SEQ: ++ case VPU_INST_STATE_PIC_RUN: ++ if (!m2m_ctx->cap_q_ctx.q.streaming) { ++ dev_dbg(inst->dev->dev, "CAPTURE queue must be streaming to queue jobs!\n"); ++ break; ++ } else if (v4l2_m2m_num_dst_bufs_ready(m2m_ctx) < (inst->fbc_buf_count - 1)) { ++ dev_dbg(inst->dev->dev, ++ "No capture buffer ready to decode!\n"); ++ break; ++ } else if (!wave5_is_draining_or_eos(inst) && ++ !v4l2_m2m_num_src_bufs_ready(m2m_ctx)) { ++ dev_dbg(inst->dev->dev, ++ "No bitstream data to decode!\n"); ++ break; ++ } ++ ret = 1; ++ break; ++ case VPU_INST_STATE_STOP: ++ dev_dbg(inst->dev->dev, "Decoder is stopped, not running.\n"); ++ break; ++ } ++ ++ spin_unlock_irqrestore(&inst->state_spinlock, flags); ++ ++ return ret; ++} ++ ++static const struct v4l2_m2m_ops wave5_vpu_dec_m2m_ops = { ++ .device_run = wave5_vpu_dec_device_run, ++ .job_abort = wave5_vpu_dec_job_abort, ++ .job_ready = wave5_vpu_dec_job_ready, ++}; ++ ++static int wave5_vpu_open_dec(struct file *filp) ++{ ++ struct video_device *vdev = video_devdata(filp); ++ struct vpu_device *dev = video_drvdata(filp); ++ struct vpu_instance *inst = NULL; ++ struct v4l2_m2m_ctx *m2m_ctx; ++ int ret = 0; ++ ++ inst = kzalloc(sizeof(*inst), GFP_KERNEL); ++ if (!inst) ++ return -ENOMEM; ++ ++ inst->dev = dev; ++ inst->type = VPU_INST_TYPE_DEC; ++ inst->ops = &wave5_vpu_dec_inst_ops; ++ ++ spin_lock_init(&inst->state_spinlock); ++ ++ inst->codec_info = kzalloc(sizeof(*inst->codec_info), GFP_KERNEL); ++ if (!inst->codec_info) ++ return -ENOMEM; ++ ++ v4l2_fh_init(&inst->v4l2_fh, vdev); ++ filp->private_data = &inst->v4l2_fh; ++ v4l2_fh_add(&inst->v4l2_fh); ++ ++ INIT_LIST_HEAD(&inst->list); ++ list_add_tail(&inst->list, &dev->instances); ++ ++ inst->v4l2_m2m_dev = inst->dev->v4l2_m2m_dec_dev; ++ inst->v4l2_fh.m2m_ctx = ++ v4l2_m2m_ctx_init(inst->v4l2_m2m_dev, inst, wave5_vpu_dec_queue_init); ++ if (IS_ERR(inst->v4l2_fh.m2m_ctx)) { ++ ret = PTR_ERR(inst->v4l2_fh.m2m_ctx); ++ goto cleanup_inst; ++ } ++ m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ ++ v4l2_m2m_set_src_buffered(m2m_ctx, true); ++ v4l2_m2m_set_dst_buffered(m2m_ctx, true); ++ /* ++ * We use the M2M job queue to ensure synchronization of steps where ++ * needed, as IOCTLs can occur at anytime and we need to run commands on ++ * the firmware in a specified order. ++ * In order to initialize the sequence on the firmware within an M2M ++ * job, the M2M framework needs to be able to queue jobs before ++ * the CAPTURE queue has been started, because we need the results of the ++ * initialization to properly prepare the CAPTURE queue with the correct ++ * amount of buffers. ++ * By setting ignore_cap_streaming to true the m2m framework will call ++ * job_ready as soon as the OUTPUT queue is streaming, instead of ++ * waiting until both the CAPTURE and OUTPUT queues are streaming. ++ */ ++ m2m_ctx->ignore_cap_streaming = true; ++ ++ v4l2_ctrl_handler_init(&inst->v4l2_ctrl_hdl, 10); ++ v4l2_ctrl_new_std(&inst->v4l2_ctrl_hdl, NULL, ++ V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 1); ++ ++ if (inst->v4l2_ctrl_hdl.error) { ++ ret = -ENODEV; ++ goto cleanup_inst; ++ } ++ ++ inst->v4l2_fh.ctrl_handler = &inst->v4l2_ctrl_hdl; ++ v4l2_ctrl_handler_setup(&inst->v4l2_ctrl_hdl); ++ ++ wave5_set_default_format(&inst->src_fmt, &inst->dst_fmt); ++ inst->colorspace = V4L2_COLORSPACE_REC709; ++ inst->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; ++ inst->quantization = V4L2_QUANTIZATION_DEFAULT; ++ inst->xfer_func = V4L2_XFER_FUNC_DEFAULT; ++ ++ init_completion(&inst->irq_done); ++ ++ inst->id = ida_alloc(&inst->dev->inst_ida, GFP_KERNEL); ++ if (inst->id < 0) { ++ dev_warn(inst->dev->dev, "Allocating instance ID, fail: %d\n", inst->id); ++ ret = inst->id; ++ goto cleanup_inst; ++ } ++ ++ wave5_vdi_allocate_sram(inst->dev); ++ ++ return 0; ++ ++cleanup_inst: ++ wave5_cleanup_instance(inst); ++ return ret; ++} ++ ++static int wave5_vpu_dec_release(struct file *filp) ++{ ++ return wave5_vpu_release_device(filp, wave5_vpu_dec_close, "decoder"); ++} ++ ++static const struct v4l2_file_operations wave5_vpu_dec_fops = { ++ .owner = THIS_MODULE, ++ .open = wave5_vpu_open_dec, ++ .release = wave5_vpu_dec_release, ++ .unlocked_ioctl = video_ioctl2, ++ .poll = v4l2_m2m_fop_poll, ++ .mmap = v4l2_m2m_fop_mmap, ++}; ++ ++int wave5_vpu_dec_register_device(struct vpu_device *dev) ++{ ++ struct video_device *vdev_dec; ++ int ret; ++ ++ vdev_dec = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_dec), GFP_KERNEL); ++ if (!vdev_dec) ++ return -ENOMEM; ++ ++ dev->v4l2_m2m_dec_dev = v4l2_m2m_init(&wave5_vpu_dec_m2m_ops); ++ if (IS_ERR(dev->v4l2_m2m_dec_dev)) { ++ ret = PTR_ERR(dev->v4l2_m2m_dec_dev); ++ dev_err(dev->dev, "v4l2_m2m_init, fail: %d\n", ret); ++ return -EINVAL; ++ } ++ ++ dev->video_dev_dec = vdev_dec; ++ ++ strscpy(vdev_dec->name, VPU_DEC_DEV_NAME, sizeof(vdev_dec->name)); ++ vdev_dec->fops = &wave5_vpu_dec_fops; ++ vdev_dec->ioctl_ops = &wave5_vpu_dec_ioctl_ops; ++ vdev_dec->release = video_device_release_empty; ++ vdev_dec->v4l2_dev = &dev->v4l2_dev; ++ vdev_dec->vfl_dir = VFL_DIR_M2M; ++ vdev_dec->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; ++ vdev_dec->lock = &dev->dev_lock; ++ ++ ret = video_register_device(vdev_dec, VFL_TYPE_VIDEO, -1); ++ if (ret) ++ return ret; ++ ++ video_set_drvdata(vdev_dec, dev); ++ ++ return 0; ++} ++ ++void wave5_vpu_dec_unregister_device(struct vpu_device *dev) ++{ ++ video_unregister_device(dev->video_dev_dec); ++ if (dev->v4l2_m2m_dec_dev) ++ v4l2_m2m_release(dev->v4l2_m2m_dec_dev); ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c +--- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,1794 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) ++/* ++ * Wave5 series multi-standard codec IP - encoder interface ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#include "wave5-helper.h" ++ ++#define VPU_ENC_DEV_NAME "C&M Wave5 VPU encoder" ++#define VPU_ENC_DRV_NAME "wave5-enc" ++ ++static const struct vpu_format enc_fmt_list[FMT_TYPES][MAX_FMTS] = { ++ [VPU_FMT_TYPE_CODEC] = { ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_HEVC, ++ .max_width = W5_MAX_ENC_PIC_WIDTH, ++ .min_width = W5_MIN_ENC_PIC_WIDTH, ++ .max_height = W5_MAX_ENC_PIC_HEIGHT, ++ .min_height = W5_MIN_ENC_PIC_HEIGHT, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_H264, ++ .max_width = W5_MAX_ENC_PIC_WIDTH, ++ .min_width = W5_MIN_ENC_PIC_WIDTH, ++ .max_height = W5_MAX_ENC_PIC_HEIGHT, ++ .min_height = W5_MIN_ENC_PIC_HEIGHT, ++ }, ++ }, ++ [VPU_FMT_TYPE_RAW] = { ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420, ++ .max_width = W5_MAX_ENC_PIC_WIDTH, ++ .min_width = W5_MIN_ENC_PIC_WIDTH, ++ .max_height = W5_MAX_ENC_PIC_HEIGHT, ++ .min_height = W5_MIN_ENC_PIC_HEIGHT, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV12, ++ .max_width = W5_MAX_ENC_PIC_WIDTH, ++ .min_width = W5_MIN_ENC_PIC_WIDTH, ++ .max_height = W5_MAX_ENC_PIC_HEIGHT, ++ .min_height = W5_MIN_ENC_PIC_HEIGHT, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV21, ++ .max_width = W5_MAX_ENC_PIC_WIDTH, ++ .min_width = W5_MIN_ENC_PIC_WIDTH, ++ .max_height = W5_MAX_ENC_PIC_HEIGHT, ++ .min_height = W5_MIN_ENC_PIC_HEIGHT, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M, ++ .max_width = W5_MAX_ENC_PIC_WIDTH, ++ .min_width = W5_MIN_ENC_PIC_WIDTH, ++ .max_height = W5_MAX_ENC_PIC_HEIGHT, ++ .min_height = W5_MIN_ENC_PIC_HEIGHT, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV12M, ++ .max_width = W5_MAX_ENC_PIC_WIDTH, ++ .min_width = W5_MIN_ENC_PIC_WIDTH, ++ .max_height = W5_MAX_ENC_PIC_HEIGHT, ++ .min_height = W5_MIN_ENC_PIC_HEIGHT, ++ }, ++ { ++ .v4l2_pix_fmt = V4L2_PIX_FMT_NV21M, ++ .max_width = W5_MAX_ENC_PIC_WIDTH, ++ .min_width = W5_MIN_ENC_PIC_WIDTH, ++ .max_height = W5_MAX_ENC_PIC_HEIGHT, ++ .min_height = W5_MIN_ENC_PIC_HEIGHT, ++ }, ++ } ++}; ++ ++static int switch_state(struct vpu_instance *inst, enum vpu_instance_state state) ++{ ++ switch (state) { ++ case VPU_INST_STATE_NONE: ++ goto invalid_state_switch; ++ case VPU_INST_STATE_OPEN: ++ if (inst->state != VPU_INST_STATE_NONE) ++ goto invalid_state_switch; ++ break; ++ case VPU_INST_STATE_INIT_SEQ: ++ if (inst->state != VPU_INST_STATE_OPEN && inst->state != VPU_INST_STATE_STOP) ++ goto invalid_state_switch; ++ break; ++ case VPU_INST_STATE_PIC_RUN: ++ if (inst->state != VPU_INST_STATE_INIT_SEQ) ++ goto invalid_state_switch; ++ break; ++ case VPU_INST_STATE_STOP: ++ break; ++ }; ++ ++ dev_dbg(inst->dev->dev, "Switch state from %s to %s.\n", ++ state_to_str(inst->state), state_to_str(state)); ++ inst->state = state; ++ return 0; ++ ++invalid_state_switch: ++ WARN(1, "Invalid state switch from %s to %s.\n", ++ state_to_str(inst->state), state_to_str(state)); ++ return -EINVAL; ++} ++ ++static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned int width, ++ unsigned int height) ++{ ++ switch (pix_mp->pixelformat) { ++ case V4L2_PIX_FMT_YUV420: ++ case V4L2_PIX_FMT_NV12: ++ case V4L2_PIX_FMT_NV21: ++ pix_mp->width = width; ++ pix_mp->height = height; ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height * 3 / 2; ++ break; ++ case V4L2_PIX_FMT_YUV420M: ++ pix_mp->width = width; ++ pix_mp->height = height; ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height; ++ pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2; ++ pix_mp->plane_fmt[1].sizeimage = round_up(width, 32) * height / 4; ++ pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2; ++ pix_mp->plane_fmt[2].sizeimage = round_up(width, 32) * height / 4; ++ break; ++ case V4L2_PIX_FMT_NV12M: ++ case V4L2_PIX_FMT_NV21M: ++ pix_mp->width = width; ++ pix_mp->height = height; ++ pix_mp->plane_fmt[0].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height; ++ pix_mp->plane_fmt[1].bytesperline = round_up(width, 32); ++ pix_mp->plane_fmt[1].sizeimage = round_up(width, 32) * height / 2; ++ break; ++ default: ++ pix_mp->width = width; ++ pix_mp->height = height; ++ pix_mp->plane_fmt[0].bytesperline = 0; ++ pix_mp->plane_fmt[0].sizeimage = width * height / 8 * 3; ++ break; ++ } ++} ++ ++static int start_encode(struct vpu_instance *inst, u32 *fail_res) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ int ret; ++ struct vb2_v4l2_buffer *src_buf; ++ struct vb2_v4l2_buffer *dst_buf; ++ struct frame_buffer frame_buf; ++ struct enc_param pic_param; ++ u32 stride = ALIGN(inst->dst_fmt.width, 32); ++ u32 luma_size = (stride * inst->dst_fmt.height); ++ u32 chroma_size = ((stride / 2) * (inst->dst_fmt.height / 2)); ++ ++ memset(&pic_param, 0, sizeof(struct enc_param)); ++ memset(&frame_buf, 0, sizeof(struct frame_buffer)); ++ ++ dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx); ++ if (!dst_buf) { ++ dev_dbg(inst->dev->dev, "%s: No destination buffer found\n", __func__); ++ return -EAGAIN; ++ } ++ ++ pic_param.pic_stream_buffer_addr = ++ vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0); ++ pic_param.pic_stream_buffer_size = ++ vb2_plane_size(&dst_buf->vb2_buf, 0); ++ ++ src_buf = v4l2_m2m_next_src_buf(m2m_ctx); ++ if (!src_buf) { ++ dev_dbg(inst->dev->dev, "%s: No source buffer found\n", __func__); ++ if (m2m_ctx->is_draining) ++ pic_param.src_end_flag = 1; ++ else ++ return -EAGAIN; ++ } else { ++ if (inst->src_fmt.num_planes == 1) { ++ frame_buf.buf_y = ++ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); ++ frame_buf.buf_cb = frame_buf.buf_y + luma_size; ++ frame_buf.buf_cr = frame_buf.buf_cb + chroma_size; ++ } else if (inst->src_fmt.num_planes == 2) { ++ frame_buf.buf_y = ++ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); ++ frame_buf.buf_cb = ++ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1); ++ frame_buf.buf_cr = frame_buf.buf_cb + chroma_size; ++ } else if (inst->src_fmt.num_planes == 3) { ++ frame_buf.buf_y = ++ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); ++ frame_buf.buf_cb = ++ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1); ++ frame_buf.buf_cr = ++ vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 2); ++ } ++ frame_buf.stride = stride; ++ pic_param.src_idx = src_buf->vb2_buf.index; ++ } ++ ++ pic_param.source_frame = &frame_buf; ++ pic_param.code_option.implicit_header_encode = 1; ++ pic_param.code_option.encode_aud = inst->encode_aud; ++ ret = wave5_vpu_enc_start_one_frame(inst, &pic_param, fail_res); ++ if (ret) { ++ if (*fail_res == WAVE5_SYSERR_QUEUEING_FAIL) ++ return -EINVAL; ++ ++ dev_dbg(inst->dev->dev, "%s: wave5_vpu_enc_start_one_frame fail: %d\n", ++ __func__, ret); ++ src_buf = v4l2_m2m_src_buf_remove(m2m_ctx); ++ if (!src_buf) { ++ dev_dbg(inst->dev->dev, ++ "%s: Removing src buf failed, the queue is empty\n", ++ __func__); ++ return -EINVAL; ++ } ++ dst_buf = v4l2_m2m_dst_buf_remove(m2m_ctx); ++ if (!dst_buf) { ++ dev_dbg(inst->dev->dev, ++ "%s: Removing dst buf failed, the queue is empty\n", ++ __func__); ++ return -EINVAL; ++ } ++ switch_state(inst, VPU_INST_STATE_STOP); ++ dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp; ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR); ++ } else { ++ dev_dbg(inst->dev->dev, "%s: wave5_vpu_enc_start_one_frame success\n", ++ __func__); ++ /* ++ * Remove the source buffer from the ready-queue now and finish ++ * it in the videobuf2 framework once the index is returned by the ++ * firmware in finish_encode ++ */ ++ if (src_buf) ++ v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, src_buf->vb2_buf.index); ++ } ++ ++ return 0; ++} ++ ++static void wave5_vpu_enc_finish_encode(struct vpu_instance *inst) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ int ret; ++ struct enc_output_info enc_output_info; ++ struct vb2_v4l2_buffer *src_buf = NULL; ++ struct vb2_v4l2_buffer *dst_buf = NULL; ++ ++ ret = wave5_vpu_enc_get_output_info(inst, &enc_output_info); ++ if (ret) { ++ dev_dbg(inst->dev->dev, ++ "%s: vpu_enc_get_output_info fail: %d reason: %u | info: %u\n", ++ __func__, ret, enc_output_info.error_reason, enc_output_info.warn_info); ++ return; ++ } ++ ++ dev_dbg(inst->dev->dev, ++ "%s: pic_type %i recon_idx %i src_idx %i pic_byte %u pts %llu\n", ++ __func__, enc_output_info.pic_type, enc_output_info.recon_frame_index, ++ enc_output_info.enc_src_idx, enc_output_info.enc_pic_byte, enc_output_info.pts); ++ ++ /* ++ * The source buffer will not be found in the ready-queue as it has been ++ * dropped after sending of the encode firmware command, locate it in ++ * the videobuf2 queue directly ++ */ ++ if (enc_output_info.enc_src_idx >= 0) { ++ struct vb2_buffer *vb = vb2_get_buffer(v4l2_m2m_get_src_vq(m2m_ctx), ++ enc_output_info.enc_src_idx); ++ if (vb->state != VB2_BUF_STATE_ACTIVE) ++ dev_warn(inst->dev->dev, ++ "%s: encoded buffer (%d) was not in ready queue %i.", ++ __func__, enc_output_info.enc_src_idx, vb->state); ++ else ++ src_buf = to_vb2_v4l2_buffer(vb); ++ ++ if (src_buf) { ++ inst->timestamp = src_buf->vb2_buf.timestamp; ++ v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); ++ } else { ++ dev_warn(inst->dev->dev, "%s: no source buffer with index: %d found\n", ++ __func__, enc_output_info.enc_src_idx); ++ } ++ } ++ ++ dst_buf = v4l2_m2m_dst_buf_remove(m2m_ctx); ++ if (enc_output_info.recon_frame_index == RECON_IDX_FLAG_ENC_END) { ++ static const struct v4l2_event vpu_event_eos = { ++ .type = V4L2_EVENT_EOS ++ }; ++ ++ if (!WARN_ON(!dst_buf)) { ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0); ++ dst_buf->field = V4L2_FIELD_NONE; ++ v4l2_m2m_last_buffer_done(m2m_ctx, dst_buf); ++ } ++ ++ v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_eos); ++ ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++ } else { ++ if (!dst_buf) { ++ dev_warn(inst->dev->dev, "No bitstream buffer."); ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++ return; ++ } ++ ++ vb2_set_plane_payload(&dst_buf->vb2_buf, 0, enc_output_info.bitstream_size); ++ ++ dst_buf->vb2_buf.timestamp = inst->timestamp; ++ dst_buf->field = V4L2_FIELD_NONE; ++ if (enc_output_info.pic_type == PIC_TYPE_I) { ++ if (enc_output_info.enc_vcl_nut == 19 || ++ enc_output_info.enc_vcl_nut == 20) ++ dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME; ++ else ++ dst_buf->flags |= V4L2_BUF_FLAG_PFRAME; ++ } else if (enc_output_info.pic_type == PIC_TYPE_P) { ++ dst_buf->flags |= V4L2_BUF_FLAG_PFRAME; ++ } else if (enc_output_info.pic_type == PIC_TYPE_B) { ++ dst_buf->flags |= V4L2_BUF_FLAG_BFRAME; ++ } ++ ++ v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE); ++ ++ dev_dbg(inst->dev->dev, "%s: frame_cycle %8u\n", ++ __func__, enc_output_info.frame_cycle); ++ ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++ } ++} ++ ++static int wave5_vpu_enc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) ++{ ++ strscpy(cap->driver, VPU_ENC_DRV_NAME, sizeof(cap->driver)); ++ strscpy(cap->card, VPU_ENC_DRV_NAME, sizeof(cap->card)); ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_enum_framesizes(struct file *f, void *fh, struct v4l2_frmsizeenum *fsize) ++{ ++ const struct vpu_format *vpu_fmt; ++ ++ if (fsize->index) ++ return -EINVAL; ++ ++ vpu_fmt = wave5_find_vpu_fmt(fsize->pixel_format, enc_fmt_list[VPU_FMT_TYPE_CODEC]); ++ if (!vpu_fmt) { ++ vpu_fmt = wave5_find_vpu_fmt(fsize->pixel_format, enc_fmt_list[VPU_FMT_TYPE_RAW]); ++ if (!vpu_fmt) ++ return -EINVAL; ++ } ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; ++ fsize->stepwise.min_width = vpu_fmt->min_width; ++ fsize->stepwise.max_width = vpu_fmt->max_width; ++ fsize->stepwise.step_width = 1; ++ fsize->stepwise.min_height = vpu_fmt->min_height; ++ fsize->stepwise.max_height = vpu_fmt->max_height; ++ fsize->stepwise.step_height = 1; ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_enum_fmt_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ const struct vpu_format *vpu_fmt; ++ ++ dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); ++ ++ vpu_fmt = wave5_find_vpu_fmt_by_idx(f->index, enc_fmt_list[VPU_FMT_TYPE_CODEC]); ++ if (!vpu_fmt) ++ return -EINVAL; ++ ++ f->pixelformat = vpu_fmt->v4l2_pix_fmt; ++ f->flags = 0; ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ const struct vpu_format *vpu_fmt; ++ ++ dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", ++ __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field); ++ ++ vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, enc_fmt_list[VPU_FMT_TYPE_CODEC]); ++ if (!vpu_fmt) { ++ f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat; ++ f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes; ++ wave5_update_pix_fmt(&f->fmt.pix_mp, inst->dst_fmt.width, inst->dst_fmt.height); ++ } else { ++ int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width); ++ int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height); ++ ++ f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt; ++ f->fmt.pix_mp.num_planes = 1; ++ wave5_update_pix_fmt(&f->fmt.pix_mp, width, height); ++ } ++ ++ f->fmt.pix_mp.flags = 0; ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ f->fmt.pix_mp.colorspace = inst->colorspace; ++ f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc; ++ f->fmt.pix_mp.quantization = inst->quantization; ++ f->fmt.pix_mp.xfer_func = inst->xfer_func; ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ int i, ret; ++ ++ dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", ++ __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field); ++ ++ ret = wave5_vpu_enc_try_fmt_cap(file, fh, f); ++ if (ret) ++ return ret; ++ ++ inst->std = wave5_to_vpu_std(f->fmt.pix_mp.pixelformat, inst->type); ++ if (inst->std == STD_UNKNOWN) { ++ dev_warn(inst->dev->dev, "unsupported pixelformat: %.4s\n", ++ (char *)&f->fmt.pix_mp.pixelformat); ++ return -EINVAL; ++ } ++ ++ inst->dst_fmt.width = f->fmt.pix_mp.width; ++ inst->dst_fmt.height = f->fmt.pix_mp.height; ++ inst->dst_fmt.pixelformat = f->fmt.pix_mp.pixelformat; ++ inst->dst_fmt.field = f->fmt.pix_mp.field; ++ inst->dst_fmt.flags = f->fmt.pix_mp.flags; ++ inst->dst_fmt.num_planes = f->fmt.pix_mp.num_planes; ++ for (i = 0; i < inst->dst_fmt.num_planes; i++) { ++ inst->dst_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline; ++ inst->dst_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; ++ } ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ int i; ++ ++ f->fmt.pix_mp.width = inst->dst_fmt.width; ++ f->fmt.pix_mp.height = inst->dst_fmt.height; ++ f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat; ++ f->fmt.pix_mp.field = inst->dst_fmt.field; ++ f->fmt.pix_mp.flags = inst->dst_fmt.flags; ++ f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes; ++ for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { ++ f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->dst_fmt.plane_fmt[i].bytesperline; ++ f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->dst_fmt.plane_fmt[i].sizeimage; ++ } ++ ++ f->fmt.pix_mp.colorspace = inst->colorspace; ++ f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc; ++ f->fmt.pix_mp.quantization = inst->quantization; ++ f->fmt.pix_mp.xfer_func = inst->xfer_func; ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_enum_fmt_out(struct file *file, void *fh, struct v4l2_fmtdesc *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ const struct vpu_format *vpu_fmt; ++ ++ dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index); ++ ++ vpu_fmt = wave5_find_vpu_fmt_by_idx(f->index, enc_fmt_list[VPU_FMT_TYPE_RAW]); ++ if (!vpu_fmt) ++ return -EINVAL; ++ ++ f->pixelformat = vpu_fmt->v4l2_pix_fmt; ++ f->flags = 0; ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ const struct vpu_format *vpu_fmt; ++ ++ dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", ++ __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field); ++ ++ vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, enc_fmt_list[VPU_FMT_TYPE_RAW]); ++ if (!vpu_fmt) { ++ f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat; ++ f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes; ++ wave5_update_pix_fmt(&f->fmt.pix_mp, inst->src_fmt.width, inst->src_fmt.height); ++ } else { ++ int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width); ++ int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height); ++ const struct v4l2_format_info *info = v4l2_format_info(vpu_fmt->v4l2_pix_fmt); ++ ++ f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt; ++ f->fmt.pix_mp.num_planes = info->mem_planes; ++ wave5_update_pix_fmt(&f->fmt.pix_mp, width, height); ++ } ++ ++ f->fmt.pix_mp.flags = 0; ++ f->fmt.pix_mp.field = V4L2_FIELD_NONE; ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ int i, ret; ++ ++ dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n", ++ __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height, ++ f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field); ++ ++ ret = wave5_vpu_enc_try_fmt_out(file, fh, f); ++ if (ret) ++ return ret; ++ ++ inst->src_fmt.width = f->fmt.pix_mp.width; ++ inst->src_fmt.height = f->fmt.pix_mp.height; ++ inst->src_fmt.pixelformat = f->fmt.pix_mp.pixelformat; ++ inst->src_fmt.field = f->fmt.pix_mp.field; ++ inst->src_fmt.flags = f->fmt.pix_mp.flags; ++ inst->src_fmt.num_planes = f->fmt.pix_mp.num_planes; ++ for (i = 0; i < inst->src_fmt.num_planes; i++) { ++ inst->src_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline; ++ inst->src_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage; ++ } ++ ++ if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12 || ++ inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12M) { ++ inst->cbcr_interleave = true; ++ inst->nv21 = false; ++ } else if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21 || ++ inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21M) { ++ inst->cbcr_interleave = true; ++ inst->nv21 = true; ++ } else { ++ inst->cbcr_interleave = false; ++ inst->nv21 = false; ++ } ++ ++ inst->colorspace = f->fmt.pix_mp.colorspace; ++ inst->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; ++ inst->quantization = f->fmt.pix_mp.quantization; ++ inst->xfer_func = f->fmt.pix_mp.xfer_func; ++ ++ wave5_update_pix_fmt(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height); ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ ++ dev_dbg(inst->dev->dev, "%s: type: %u | target: %u\n", __func__, s->type, s->target); ++ ++ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ switch (s->target) { ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ case V4L2_SEL_TGT_CROP: ++ s->r.left = 0; ++ s->r.top = 0; ++ s->r.width = inst->dst_fmt.width; ++ s->r.height = inst->dst_fmt.height; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_s_selection(struct file *file, void *fh, struct v4l2_selection *s) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ ++ if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ++ return -EINVAL; ++ ++ if (s->target != V4L2_SEL_TGT_CROP) ++ return -EINVAL; ++ ++ dev_dbg(inst->dev->dev, "%s: V4L2_SEL_TGT_CROP width: %u | height: %u\n", ++ __func__, s->r.width, s->r.height); ++ ++ s->r.left = 0; ++ s->r.top = 0; ++ s->r.width = inst->src_fmt.width; ++ s->r.height = inst->src_fmt.height; ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *ec) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ int ret; ++ ++ ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec); ++ if (ret) ++ return ret; ++ ++ if (!wave5_vpu_both_queues_are_streaming(inst)) ++ return 0; ++ ++ switch (ec->cmd) { ++ case V4L2_ENC_CMD_STOP: ++ if (m2m_ctx->is_draining) ++ return -EBUSY; ++ ++ if (m2m_ctx->has_stopped) ++ return 0; ++ ++ m2m_ctx->last_src_buf = v4l2_m2m_last_src_buf(m2m_ctx); ++ m2m_ctx->is_draining = true; ++ break; ++ case V4L2_ENC_CMD_START: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ ++ dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, a->type); ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ++ return -EINVAL; ++ ++ a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; ++ a->parm.output.timeperframe.numerator = 1; ++ a->parm.output.timeperframe.denominator = inst->frame_rate; ++ ++ dev_dbg(inst->dev->dev, "%s: numerator: %u | denominator: %u\n", ++ __func__, a->parm.output.timeperframe.numerator, ++ a->parm.output.timeperframe.denominator); ++ ++ return 0; ++} ++ ++static int wave5_vpu_enc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) ++{ ++ struct vpu_instance *inst = wave5_to_vpu_inst(fh); ++ ++ dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, a->type); ++ ++ if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ++ return -EINVAL; ++ ++ a->parm.output.capability = V4L2_CAP_TIMEPERFRAME; ++ if (a->parm.output.timeperframe.denominator && a->parm.output.timeperframe.numerator) { ++ inst->frame_rate = a->parm.output.timeperframe.denominator / ++ a->parm.output.timeperframe.numerator; ++ } else { ++ a->parm.output.timeperframe.numerator = 1; ++ a->parm.output.timeperframe.denominator = inst->frame_rate; ++ } ++ ++ dev_dbg(inst->dev->dev, "%s: numerator: %u | denominator: %u\n", ++ __func__, a->parm.output.timeperframe.numerator, ++ a->parm.output.timeperframe.denominator); ++ ++ return 0; ++} ++ ++static const struct v4l2_ioctl_ops wave5_vpu_enc_ioctl_ops = { ++ .vidioc_querycap = wave5_vpu_enc_querycap, ++ .vidioc_enum_framesizes = wave5_vpu_enc_enum_framesizes, ++ ++ .vidioc_enum_fmt_vid_cap = wave5_vpu_enc_enum_fmt_cap, ++ .vidioc_s_fmt_vid_cap_mplane = wave5_vpu_enc_s_fmt_cap, ++ .vidioc_g_fmt_vid_cap_mplane = wave5_vpu_enc_g_fmt_cap, ++ .vidioc_try_fmt_vid_cap_mplane = wave5_vpu_enc_try_fmt_cap, ++ ++ .vidioc_enum_fmt_vid_out = wave5_vpu_enc_enum_fmt_out, ++ .vidioc_s_fmt_vid_out_mplane = wave5_vpu_enc_s_fmt_out, ++ .vidioc_g_fmt_vid_out_mplane = wave5_vpu_g_fmt_out, ++ .vidioc_try_fmt_vid_out_mplane = wave5_vpu_enc_try_fmt_out, ++ ++ .vidioc_g_selection = wave5_vpu_enc_g_selection, ++ .vidioc_s_selection = wave5_vpu_enc_s_selection, ++ ++ .vidioc_g_parm = wave5_vpu_enc_g_parm, ++ .vidioc_s_parm = wave5_vpu_enc_s_parm, ++ ++ .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, ++ .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, ++ .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, ++ .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, ++ .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, ++ .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, ++ .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, ++ .vidioc_streamon = v4l2_m2m_ioctl_streamon, ++ .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, ++ ++ .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd, ++ .vidioc_encoder_cmd = wave5_vpu_enc_encoder_cmd, ++ ++ .vidioc_subscribe_event = wave5_vpu_subscribe_event, ++ .vidioc_unsubscribe_event = v4l2_event_unsubscribe, ++}; ++ ++static int wave5_vpu_enc_s_ctrl(struct v4l2_ctrl *ctrl) ++{ ++ struct vpu_instance *inst = wave5_ctrl_to_vpu_inst(ctrl); ++ ++ dev_dbg(inst->dev->dev, "%s: name: %s | value: %d\n", __func__, ctrl->name, ctrl->val); ++ ++ switch (ctrl->id) { ++ case V4L2_CID_MPEG_VIDEO_AU_DELIMITER: ++ inst->encode_aud = ctrl->val; ++ break; ++ case V4L2_CID_HFLIP: ++ inst->mirror_direction |= (ctrl->val << 1); ++ break; ++ case V4L2_CID_VFLIP: ++ inst->mirror_direction |= ctrl->val; ++ break; ++ case V4L2_CID_ROTATE: ++ inst->rot_angle = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_VBV_SIZE: ++ inst->vbv_buf_size = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR: ++ inst->rc_mode = 0; ++ break; ++ case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR: ++ inst->rc_mode = 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case V4L2_CID_MPEG_VIDEO_BITRATE: ++ inst->bit_rate = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_GOP_SIZE: ++ inst->enc_param.avc_idr_period = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE: ++ inst->enc_param.independ_slice_mode = ctrl->val; ++ inst->enc_param.avc_slice_mode = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB: ++ inst->enc_param.independ_slice_mode_arg = ctrl->val; ++ inst->enc_param.avc_slice_arg = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: ++ inst->rc_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: ++ inst->enc_param.mb_level_rc_enable = ctrl->val; ++ inst->enc_param.cu_level_rc_enable = ctrl->val; ++ inst->enc_param.hvs_qp_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN: ++ inst->enc_param.profile = HEVC_PROFILE_MAIN; ++ inst->bit_depth = 8; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE: ++ inst->enc_param.profile = HEVC_PROFILE_STILLPICTURE; ++ inst->enc_param.en_still_picture = 1; ++ inst->bit_depth = 8; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10: ++ inst->enc_param.profile = HEVC_PROFILE_MAIN10; ++ inst->bit_depth = 10; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_1: ++ inst->enc_param.level = 10 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2: ++ inst->enc_param.level = 20 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1: ++ inst->enc_param.level = 21 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3: ++ inst->enc_param.level = 30 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1: ++ inst->enc_param.level = 31 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4: ++ inst->enc_param.level = 40 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1: ++ inst->enc_param.level = 41 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5: ++ inst->enc_param.level = 50 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1: ++ inst->enc_param.level = 51 * 3; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2: ++ inst->enc_param.level = 52 * 3; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP: ++ inst->enc_param.min_qp_i = ctrl->val; ++ inst->enc_param.min_qp_p = ctrl->val; ++ inst->enc_param.min_qp_b = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP: ++ inst->enc_param.max_qp_i = ctrl->val; ++ inst->enc_param.max_qp_p = ctrl->val; ++ inst->enc_param.max_qp_b = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: ++ inst->enc_param.intra_qp = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE: ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED: ++ inst->enc_param.disable_deblk = 1; ++ inst->enc_param.sao_enable = 0; ++ inst->enc_param.lf_cross_slice_boundary_enable = 0; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED: ++ inst->enc_param.disable_deblk = 0; ++ inst->enc_param.sao_enable = 1; ++ inst->enc_param.lf_cross_slice_boundary_enable = 1; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY: ++ inst->enc_param.disable_deblk = 0; ++ inst->enc_param.sao_enable = 1; ++ inst->enc_param.lf_cross_slice_boundary_enable = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2: ++ inst->enc_param.beta_offset_div2 = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2: ++ inst->enc_param.tc_offset_div2 = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE: ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_HEVC_REFRESH_NONE: ++ inst->enc_param.decoding_refresh_type = 0; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_REFRESH_CRA: ++ inst->enc_param.decoding_refresh_type = 1; ++ break; ++ case V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR: ++ inst->enc_param.decoding_refresh_type = 2; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD: ++ inst->enc_param.intra_period = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU: ++ inst->enc_param.lossless_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED: ++ inst->enc_param.const_intra_pred_flag = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT: ++ inst->enc_param.wpp_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING: ++ inst->enc_param.strong_intra_smooth_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1: ++ inst->enc_param.max_num_merge = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION: ++ inst->enc_param.tmvp_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_PROFILE: ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: ++ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: ++ inst->enc_param.profile = H264_PROFILE_BP; ++ inst->bit_depth = 8; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: ++ inst->enc_param.profile = H264_PROFILE_MP; ++ inst->bit_depth = 8; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED: ++ inst->enc_param.profile = H264_PROFILE_EXTENDED; ++ inst->bit_depth = 8; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: ++ inst->enc_param.profile = H264_PROFILE_HP; ++ inst->bit_depth = 8; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10: ++ inst->enc_param.profile = H264_PROFILE_HIGH10; ++ inst->bit_depth = 10; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422: ++ inst->enc_param.profile = H264_PROFILE_HIGH422; ++ inst->bit_depth = 10; ++ break; ++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE: ++ inst->enc_param.profile = H264_PROFILE_HIGH444; ++ inst->bit_depth = 10; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_LEVEL: ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: ++ inst->enc_param.level = 10; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1B: ++ inst->enc_param.level = 9; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: ++ inst->enc_param.level = 11; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: ++ inst->enc_param.level = 12; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: ++ inst->enc_param.level = 13; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: ++ inst->enc_param.level = 20; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: ++ inst->enc_param.level = 21; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: ++ inst->enc_param.level = 22; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: ++ inst->enc_param.level = 30; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: ++ inst->enc_param.level = 31; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: ++ inst->enc_param.level = 32; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: ++ inst->enc_param.level = 40; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_1: ++ inst->enc_param.level = 41; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_2: ++ inst->enc_param.level = 42; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_5_0: ++ inst->enc_param.level = 50; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LEVEL_5_1: ++ inst->enc_param.level = 51; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP: ++ inst->enc_param.min_qp_i = ctrl->val; ++ inst->enc_param.min_qp_p = ctrl->val; ++ inst->enc_param.min_qp_b = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_MAX_QP: ++ inst->enc_param.max_qp_i = ctrl->val; ++ inst->enc_param.max_qp_p = ctrl->val; ++ inst->enc_param.max_qp_b = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: ++ inst->enc_param.intra_qp = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: ++ switch (ctrl->val) { ++ case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED: ++ inst->enc_param.disable_deblk = 1; ++ inst->enc_param.lf_cross_slice_boundary_enable = 1; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED: ++ inst->enc_param.disable_deblk = 0; ++ inst->enc_param.lf_cross_slice_boundary_enable = 1; ++ break; ++ case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY: ++ inst->enc_param.disable_deblk = 0; ++ inst->enc_param.lf_cross_slice_boundary_enable = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA: ++ inst->enc_param.beta_offset_div2 = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA: ++ inst->enc_param.tc_offset_div2 = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM: ++ inst->enc_param.transform8x8_enable = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION: ++ inst->enc_param.const_intra_pred_flag = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET: ++ inst->enc_param.chroma_cb_qp_offset = ctrl->val; ++ inst->enc_param.chroma_cr_qp_offset = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: ++ inst->enc_param.intra_period = ctrl->val; ++ break; ++ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: ++ inst->enc_param.entropy_coding_mode = ctrl->val; ++ break; ++ case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct v4l2_ctrl_ops wave5_vpu_enc_ctrl_ops = { ++ .s_ctrl = wave5_vpu_enc_s_ctrl, ++}; ++ ++static int wave5_vpu_enc_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, ++ unsigned int *num_planes, unsigned int sizes[], ++ struct device *alloc_devs[]) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ struct v4l2_pix_format_mplane inst_format = ++ (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->dst_fmt; ++ unsigned int i; ++ ++ dev_dbg(inst->dev->dev, "%s: num_buffers: %u | num_planes: %u | type: %u\n", __func__, ++ *num_buffers, *num_planes, q->type); ++ ++ if (*num_planes) { ++ if (inst_format.num_planes != *num_planes) ++ return -EINVAL; ++ ++ for (i = 0; i < *num_planes; i++) { ++ if (sizes[i] < inst_format.plane_fmt[i].sizeimage) ++ return -EINVAL; ++ } ++ } else { ++ *num_planes = inst_format.num_planes; ++ for (i = 0; i < *num_planes; i++) { ++ sizes[i] = inst_format.plane_fmt[i].sizeimage; ++ dev_dbg(inst->dev->dev, "%s: size[%u]: %u\n", __func__, i, sizes[i]); ++ } ++ } ++ ++ dev_dbg(inst->dev->dev, "%s: size: %u\n", __func__, sizes[0]); ++ ++ return 0; ++} ++ ++static void wave5_vpu_enc_buf_queue(struct vb2_buffer *vb) ++{ ++ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); ++ struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ ++ dev_dbg(inst->dev->dev, "%s: type: %4u index: %4u size: ([0]=%4lu, [1]=%4lu, [2]=%4lu)\n", ++ __func__, vb->type, vb->index, vb2_plane_size(&vbuf->vb2_buf, 0), ++ vb2_plane_size(&vbuf->vb2_buf, 1), vb2_plane_size(&vbuf->vb2_buf, 2)); ++ ++ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ++ vbuf->sequence = inst->queued_src_buf_num++; ++ else ++ vbuf->sequence = inst->queued_dst_buf_num++; ++ ++ v4l2_m2m_buf_queue(m2m_ctx, vbuf); ++} ++ ++static void wave5_set_enc_openparam(struct enc_open_param *open_param, ++ struct vpu_instance *inst) ++{ ++ struct enc_wave_param input = inst->enc_param; ++ u32 num_ctu_row = ALIGN(inst->dst_fmt.height, 64) / 64; ++ u32 num_mb_row = ALIGN(inst->dst_fmt.height, 16) / 16; ++ ++ open_param->wave_param.gop_preset_idx = PRESET_IDX_IPP_SINGLE; ++ open_param->wave_param.hvs_qp_scale = 2; ++ open_param->wave_param.hvs_max_delta_qp = 10; ++ open_param->wave_param.skip_intra_trans = 1; ++ open_param->wave_param.intra_nx_n_enable = 1; ++ open_param->wave_param.nr_intra_weight_y = 7; ++ open_param->wave_param.nr_intra_weight_cb = 7; ++ open_param->wave_param.nr_intra_weight_cr = 7; ++ open_param->wave_param.nr_inter_weight_y = 4; ++ open_param->wave_param.nr_inter_weight_cb = 4; ++ open_param->wave_param.nr_inter_weight_cr = 4; ++ open_param->wave_param.rdo_skip = 1; ++ open_param->wave_param.lambda_scaling_enable = 1; ++ ++ open_param->line_buf_int_en = true; ++ open_param->pic_width = inst->dst_fmt.width; ++ open_param->pic_height = inst->dst_fmt.height; ++ open_param->frame_rate_info = inst->frame_rate; ++ open_param->rc_enable = inst->rc_enable; ++ if (inst->rc_enable) { ++ open_param->wave_param.initial_rc_qp = -1; ++ open_param->wave_param.rc_weight_param = 16; ++ open_param->wave_param.rc_weight_buf = 128; ++ } ++ open_param->wave_param.mb_level_rc_enable = input.mb_level_rc_enable; ++ open_param->wave_param.cu_level_rc_enable = input.cu_level_rc_enable; ++ open_param->wave_param.hvs_qp_enable = input.hvs_qp_enable; ++ open_param->bit_rate = inst->bit_rate; ++ open_param->vbv_buffer_size = inst->vbv_buf_size; ++ if (inst->rc_mode == 0) ++ open_param->vbv_buffer_size = 3000; ++ open_param->wave_param.profile = input.profile; ++ open_param->wave_param.en_still_picture = input.en_still_picture; ++ open_param->wave_param.level = input.level; ++ open_param->wave_param.internal_bit_depth = inst->bit_depth; ++ open_param->wave_param.intra_qp = input.intra_qp; ++ open_param->wave_param.min_qp_i = input.min_qp_i; ++ open_param->wave_param.max_qp_i = input.max_qp_i; ++ open_param->wave_param.min_qp_p = input.min_qp_p; ++ open_param->wave_param.max_qp_p = input.max_qp_p; ++ open_param->wave_param.min_qp_b = input.min_qp_b; ++ open_param->wave_param.max_qp_b = input.max_qp_b; ++ open_param->wave_param.disable_deblk = input.disable_deblk; ++ open_param->wave_param.lf_cross_slice_boundary_enable = ++ input.lf_cross_slice_boundary_enable; ++ open_param->wave_param.tc_offset_div2 = input.tc_offset_div2; ++ open_param->wave_param.beta_offset_div2 = input.beta_offset_div2; ++ open_param->wave_param.decoding_refresh_type = input.decoding_refresh_type; ++ open_param->wave_param.intra_period = input.intra_period; ++ if (inst->std == W_HEVC_ENC) { ++ if (input.intra_period == 0) { ++ open_param->wave_param.decoding_refresh_type = DEC_REFRESH_TYPE_IDR; ++ open_param->wave_param.intra_period = input.avc_idr_period; ++ } ++ } else { ++ open_param->wave_param.avc_idr_period = input.avc_idr_period; ++ } ++ open_param->wave_param.entropy_coding_mode = input.entropy_coding_mode; ++ open_param->wave_param.lossless_enable = input.lossless_enable; ++ open_param->wave_param.const_intra_pred_flag = input.const_intra_pred_flag; ++ open_param->wave_param.wpp_enable = input.wpp_enable; ++ open_param->wave_param.strong_intra_smooth_enable = input.strong_intra_smooth_enable; ++ open_param->wave_param.max_num_merge = input.max_num_merge; ++ open_param->wave_param.tmvp_enable = input.tmvp_enable; ++ open_param->wave_param.transform8x8_enable = input.transform8x8_enable; ++ open_param->wave_param.chroma_cb_qp_offset = input.chroma_cb_qp_offset; ++ open_param->wave_param.chroma_cr_qp_offset = input.chroma_cr_qp_offset; ++ open_param->wave_param.independ_slice_mode = input.independ_slice_mode; ++ open_param->wave_param.independ_slice_mode_arg = input.independ_slice_mode_arg; ++ open_param->wave_param.avc_slice_mode = input.avc_slice_mode; ++ open_param->wave_param.avc_slice_arg = input.avc_slice_arg; ++ open_param->wave_param.intra_mb_refresh_mode = input.intra_mb_refresh_mode; ++ if (input.intra_mb_refresh_mode != REFRESH_MB_MODE_NONE) { ++ if (num_mb_row >= input.intra_mb_refresh_arg) ++ open_param->wave_param.intra_mb_refresh_arg = ++ num_mb_row / input.intra_mb_refresh_arg; ++ else ++ open_param->wave_param.intra_mb_refresh_arg = num_mb_row; ++ } ++ open_param->wave_param.intra_refresh_mode = input.intra_refresh_mode; ++ if (input.intra_refresh_mode != 0) { ++ if (num_ctu_row >= input.intra_refresh_arg) ++ open_param->wave_param.intra_refresh_arg = ++ num_ctu_row / input.intra_refresh_arg; ++ else ++ open_param->wave_param.intra_refresh_arg = num_ctu_row; ++ } ++} ++ ++static int initialize_sequence(struct vpu_instance *inst) ++{ ++ struct enc_initial_info initial_info; ++ struct v4l2_ctrl *ctrl; ++ int ret; ++ ++ ret = wave5_vpu_enc_issue_seq_init(inst); ++ if (ret) { ++ dev_err(inst->dev->dev, "%s: wave5_vpu_enc_issue_seq_init, fail: %d\n", ++ __func__, ret); ++ return ret; ++ } ++ ++ if (wave5_vpu_wait_interrupt(inst, VPU_ENC_TIMEOUT) < 0) { ++ dev_err(inst->dev->dev, "%s: wave5_vpu_wait_interrupt failed\n", __func__); ++ return -EINVAL; ++ } ++ ++ ret = wave5_vpu_enc_complete_seq_init(inst, &initial_info); ++ if (ret) ++ return ret; ++ ++ dev_dbg(inst->dev->dev, "%s: min_frame_buffer: %u | min_source_buffer: %u\n", ++ __func__, initial_info.min_frame_buffer_count, ++ initial_info.min_src_frame_count); ++ inst->min_src_buf_count = initial_info.min_src_frame_count + ++ COMMAND_QUEUE_DEPTH; ++ ++ ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl, ++ V4L2_CID_MIN_BUFFERS_FOR_OUTPUT); ++ if (ctrl) ++ v4l2_ctrl_s_ctrl(ctrl, inst->min_src_buf_count); ++ ++ inst->fbc_buf_count = initial_info.min_frame_buffer_count; ++ ++ return 0; ++} ++ ++static int prepare_fb(struct vpu_instance *inst) ++{ ++ u32 fb_stride = ALIGN(inst->dst_fmt.width, 32); ++ u32 fb_height = ALIGN(inst->dst_fmt.height, 32); ++ int i, ret = 0; ++ ++ for (i = 0; i < inst->fbc_buf_count; i++) { ++ u32 luma_size = fb_stride * fb_height; ++ u32 chroma_size = ALIGN(fb_stride / 2, 16) * fb_height; ++ ++ inst->frame_vbuf[i].size = luma_size + chroma_size; ++ ret = wave5_vdi_allocate_dma_memory(inst->dev, &inst->frame_vbuf[i]); ++ if (ret < 0) { ++ dev_err(inst->dev->dev, "%s: failed to allocate FBC buffer %zu\n", ++ __func__, inst->frame_vbuf[i].size); ++ goto free_buffers; ++ } ++ ++ inst->frame_buf[i].buf_y = inst->frame_vbuf[i].daddr; ++ inst->frame_buf[i].buf_cb = (dma_addr_t)-1; ++ inst->frame_buf[i].buf_cr = (dma_addr_t)-1; ++ inst->frame_buf[i].update_fb_info = true; ++ inst->frame_buf[i].size = inst->frame_vbuf[i].size; ++ } ++ ++ ret = wave5_vpu_enc_register_frame_buffer(inst, inst->fbc_buf_count, fb_stride, ++ fb_height, COMPRESSED_FRAME_MAP); ++ if (ret) { ++ dev_err(inst->dev->dev, ++ "%s: wave5_vpu_enc_register_frame_buffer, fail: %d\n", ++ __func__, ret); ++ goto free_buffers; ++ } ++ ++ return 0; ++free_buffers: ++ for (i = 0; i < inst->fbc_buf_count; i++) ++ wave5_vpu_dec_reset_framebuffer(inst, i); ++ return ret; ++} ++ ++static int wave5_vpu_enc_start_streaming(struct vb2_queue *q, unsigned int count) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ int ret = 0; ++ ++ v4l2_m2m_update_start_streaming_state(m2m_ctx, q); ++ ++ if (inst->state == VPU_INST_STATE_NONE && q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { ++ struct enc_open_param open_param; ++ ++ memset(&open_param, 0, sizeof(struct enc_open_param)); ++ ++ wave5_set_enc_openparam(&open_param, inst); ++ ++ ret = wave5_vpu_enc_open(inst, &open_param); ++ if (ret) { ++ dev_dbg(inst->dev->dev, "%s: wave5_vpu_enc_open, fail: %d\n", ++ __func__, ret); ++ goto return_buffers; ++ } ++ ++ if (inst->mirror_direction) { ++ wave5_vpu_enc_give_command(inst, ENABLE_MIRRORING, NULL); ++ wave5_vpu_enc_give_command(inst, SET_MIRROR_DIRECTION, ++ &inst->mirror_direction); ++ } ++ if (inst->rot_angle) { ++ wave5_vpu_enc_give_command(inst, ENABLE_ROTATION, NULL); ++ wave5_vpu_enc_give_command(inst, SET_ROTATION_ANGLE, &inst->rot_angle); ++ } ++ ++ ret = switch_state(inst, VPU_INST_STATE_OPEN); ++ if (ret) ++ goto return_buffers; ++ } ++ if (inst->state == VPU_INST_STATE_OPEN && m2m_ctx->cap_q_ctx.q.streaming) { ++ ret = initialize_sequence(inst); ++ if (ret) { ++ dev_warn(inst->dev->dev, "Sequence not found: %d\n", ret); ++ goto return_buffers; ++ } ++ ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ); ++ if (ret) ++ goto return_buffers; ++ /* ++ * The sequence must be analyzed first to calculate the proper ++ * size of the auxiliary buffers. ++ */ ++ ret = prepare_fb(inst); ++ if (ret) { ++ dev_warn(inst->dev->dev, "Framebuffer preparation, fail: %d\n", ret); ++ goto return_buffers; ++ } ++ ++ ret = switch_state(inst, VPU_INST_STATE_PIC_RUN); ++ } ++ if (ret) ++ goto return_buffers; ++ ++ return 0; ++return_buffers: ++ wave5_return_bufs(q, VB2_BUF_STATE_QUEUED); ++ return ret; ++} ++ ++static void streamoff_output(struct vpu_instance *inst, struct vb2_queue *q) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct vb2_v4l2_buffer *buf; ++ ++ while ((buf = v4l2_m2m_src_buf_remove(m2m_ctx))) { ++ dev_dbg(inst->dev->dev, "%s: buf type %4u | index %4u\n", ++ __func__, buf->vb2_buf.type, buf->vb2_buf.index); ++ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); ++ } ++} ++ ++static void streamoff_capture(struct vpu_instance *inst, struct vb2_queue *q) ++{ ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ struct vb2_v4l2_buffer *buf; ++ ++ while ((buf = v4l2_m2m_dst_buf_remove(m2m_ctx))) { ++ dev_dbg(inst->dev->dev, "%s: buf type %4u | index %4u\n", ++ __func__, buf->vb2_buf.type, buf->vb2_buf.index); ++ vb2_set_plane_payload(&buf->vb2_buf, 0, 0); ++ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); ++ } ++ ++ v4l2_m2m_clear_state(m2m_ctx); ++} ++ ++static void wave5_vpu_enc_stop_streaming(struct vb2_queue *q) ++{ ++ struct vpu_instance *inst = vb2_get_drv_priv(q); ++ bool check_cmd = true; ++ ++ /* ++ * Note that we don't need m2m_ctx->next_buf_last for this driver, so we ++ * don't call v4l2_m2m_update_stop_streaming_state(). ++ */ ++ ++ dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type); ++ ++ if (wave5_vpu_both_queues_are_streaming(inst)) ++ switch_state(inst, VPU_INST_STATE_STOP); ++ ++ while (check_cmd) { ++ struct queue_status_info q_status; ++ struct enc_output_info enc_output_info; ++ ++ wave5_vpu_enc_give_command(inst, ENC_GET_QUEUE_STATUS, &q_status); ++ ++ if (q_status.report_queue_count == 0) ++ break; ++ ++ if (wave5_vpu_wait_interrupt(inst, VPU_ENC_TIMEOUT) < 0) ++ break; ++ ++ if (wave5_vpu_enc_get_output_info(inst, &enc_output_info)) ++ dev_dbg(inst->dev->dev, "Getting encoding results from fw, fail\n"); ++ } ++ ++ if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ++ streamoff_output(inst, q); ++ else ++ streamoff_capture(inst, q); ++} ++ ++static const struct vb2_ops wave5_vpu_enc_vb2_ops = { ++ .queue_setup = wave5_vpu_enc_queue_setup, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++ .buf_queue = wave5_vpu_enc_buf_queue, ++ .start_streaming = wave5_vpu_enc_start_streaming, ++ .stop_streaming = wave5_vpu_enc_stop_streaming, ++}; ++ ++static void wave5_set_default_format(struct v4l2_pix_format_mplane *src_fmt, ++ struct v4l2_pix_format_mplane *dst_fmt) ++{ ++ unsigned int src_pix_fmt = enc_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt; ++ const struct v4l2_format_info *src_fmt_info = v4l2_format_info(src_pix_fmt); ++ ++ src_fmt->pixelformat = src_pix_fmt; ++ src_fmt->field = V4L2_FIELD_NONE; ++ src_fmt->flags = 0; ++ src_fmt->num_planes = src_fmt_info->mem_planes; ++ wave5_update_pix_fmt(src_fmt, 416, 240); ++ ++ dst_fmt->pixelformat = enc_fmt_list[VPU_FMT_TYPE_CODEC][0].v4l2_pix_fmt; ++ dst_fmt->field = V4L2_FIELD_NONE; ++ dst_fmt->flags = 0; ++ dst_fmt->num_planes = 1; ++ wave5_update_pix_fmt(dst_fmt, 416, 240); ++} ++ ++static int wave5_vpu_enc_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) ++{ ++ return wave5_vpu_queue_init(priv, src_vq, dst_vq, &wave5_vpu_enc_vb2_ops); ++} ++ ++static const struct vpu_instance_ops wave5_vpu_enc_inst_ops = { ++ .finish_process = wave5_vpu_enc_finish_encode, ++}; ++ ++static void wave5_vpu_enc_device_run(void *priv) ++{ ++ struct vpu_instance *inst = priv; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ u32 fail_res = 0; ++ int ret = 0; ++ ++ switch (inst->state) { ++ case VPU_INST_STATE_PIC_RUN: ++ ret = start_encode(inst, &fail_res); ++ if (ret) { ++ if (ret == -EINVAL) ++ dev_err(inst->dev->dev, ++ "Frame encoding on m2m context (%p), fail: %d (res: %d)\n", ++ m2m_ctx, ret, fail_res); ++ else if (ret == -EAGAIN) ++ dev_dbg(inst->dev->dev, "Missing buffers for encode, try again\n"); ++ break; ++ } ++ dev_dbg(inst->dev->dev, "%s: leave with active job", __func__); ++ return; ++ default: ++ WARN(1, "Execution of a job in state %s is invalid.\n", ++ state_to_str(inst->state)); ++ break; ++ } ++ dev_dbg(inst->dev->dev, "%s: leave and finish job", __func__); ++ v4l2_m2m_job_finish(inst->v4l2_m2m_dev, m2m_ctx); ++} ++ ++static int wave5_vpu_enc_job_ready(void *priv) ++{ ++ struct vpu_instance *inst = priv; ++ struct v4l2_m2m_ctx *m2m_ctx = inst->v4l2_fh.m2m_ctx; ++ ++ switch (inst->state) { ++ case VPU_INST_STATE_NONE: ++ dev_dbg(inst->dev->dev, "Encoder must be open to start queueing M2M jobs!\n"); ++ return false; ++ case VPU_INST_STATE_PIC_RUN: ++ if (m2m_ctx->is_draining || v4l2_m2m_num_src_bufs_ready(m2m_ctx)) { ++ dev_dbg(inst->dev->dev, "Encoder ready for a job, state: %s\n", ++ state_to_str(inst->state)); ++ return true; ++ } ++ fallthrough; ++ default: ++ dev_dbg(inst->dev->dev, ++ "Encoder not ready for a job, state: %s, %s draining, %d src bufs ready\n", ++ state_to_str(inst->state), m2m_ctx->is_draining ? "is" : "is not", ++ v4l2_m2m_num_src_bufs_ready(m2m_ctx)); ++ break; ++ } ++ return false; ++} ++ ++static const struct v4l2_m2m_ops wave5_vpu_enc_m2m_ops = { ++ .device_run = wave5_vpu_enc_device_run, ++ .job_ready = wave5_vpu_enc_job_ready, ++}; ++ ++static int wave5_vpu_open_enc(struct file *filp) ++{ ++ struct video_device *vdev = video_devdata(filp); ++ struct vpu_device *dev = video_drvdata(filp); ++ struct vpu_instance *inst = NULL; ++ struct v4l2_ctrl_handler *v4l2_ctrl_hdl; ++ int ret = 0; ++ ++ inst = kzalloc(sizeof(*inst), GFP_KERNEL); ++ if (!inst) ++ return -ENOMEM; ++ v4l2_ctrl_hdl = &inst->v4l2_ctrl_hdl; ++ ++ inst->dev = dev; ++ inst->type = VPU_INST_TYPE_ENC; ++ inst->ops = &wave5_vpu_enc_inst_ops; ++ ++ inst->codec_info = kzalloc(sizeof(*inst->codec_info), GFP_KERNEL); ++ if (!inst->codec_info) ++ return -ENOMEM; ++ ++ v4l2_fh_init(&inst->v4l2_fh, vdev); ++ filp->private_data = &inst->v4l2_fh; ++ v4l2_fh_add(&inst->v4l2_fh); ++ ++ INIT_LIST_HEAD(&inst->list); ++ list_add_tail(&inst->list, &dev->instances); ++ ++ inst->v4l2_m2m_dev = inst->dev->v4l2_m2m_enc_dev; ++ inst->v4l2_fh.m2m_ctx = ++ v4l2_m2m_ctx_init(inst->v4l2_m2m_dev, inst, wave5_vpu_enc_queue_init); ++ if (IS_ERR(inst->v4l2_fh.m2m_ctx)) { ++ ret = PTR_ERR(inst->v4l2_fh.m2m_ctx); ++ goto cleanup_inst; ++ } ++ v4l2_m2m_set_src_buffered(inst->v4l2_fh.m2m_ctx, true); ++ ++ v4l2_ctrl_handler_init(v4l2_ctrl_hdl, 50); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, ++ V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, 0, ++ V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, ++ V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1, 0, ++ V4L2_MPEG_VIDEO_HEVC_LEVEL_1); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP, ++ 0, 63, 1, 8); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP, ++ 0, 63, 1, 51); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP, ++ 0, 63, 1, 30); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE, ++ V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY, 0, ++ V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2, ++ -6, 6, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2, ++ -6, 6, 1, 0); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE, ++ V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR, 0, ++ V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD, ++ 0, 2047, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING, ++ 0, 1, 1, 1); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1, ++ 1, 2, 1, 2); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION, ++ 0, 1, 1, 1); ++ ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_PROFILE, ++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE, 0, ++ V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LEVEL, ++ V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 0, ++ V4L2_MPEG_VIDEO_H264_LEVEL_1_0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_MIN_QP, ++ 0, 63, 1, 8); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_MAX_QP, ++ 0, 63, 1, 51); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, ++ 0, 63, 1, 30); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, ++ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY, 0, ++ V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, ++ -6, 6, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, ++ -6, 6, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, ++ 0, 1, 1, 1); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, ++ -12, 12, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, ++ 0, 2047, 1, 0); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, ++ V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, 0, ++ V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_AU_DELIMITER, ++ 0, 1, 1, 1); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_HFLIP, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_VFLIP, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_ROTATE, ++ 0, 270, 90, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_VBV_SIZE, ++ 10, 3000, 1, 1000); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_BITRATE_MODE, ++ V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0, ++ V4L2_MPEG_VIDEO_BITRATE_MODE_CBR); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_BITRATE, ++ 0, 700000000, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_GOP_SIZE, ++ 0, 2047, 1, 0); ++ v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, ++ V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB, 0, ++ V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, ++ 0, 0xFFFF, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, ++ 0, 1, 1, 0); ++ v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops, ++ V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 1); ++ ++ if (v4l2_ctrl_hdl->error) { ++ ret = -ENODEV; ++ goto cleanup_inst; ++ } ++ ++ inst->v4l2_fh.ctrl_handler = v4l2_ctrl_hdl; ++ v4l2_ctrl_handler_setup(v4l2_ctrl_hdl); ++ ++ wave5_set_default_format(&inst->src_fmt, &inst->dst_fmt); ++ inst->colorspace = V4L2_COLORSPACE_REC709; ++ inst->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; ++ inst->quantization = V4L2_QUANTIZATION_DEFAULT; ++ inst->xfer_func = V4L2_XFER_FUNC_DEFAULT; ++ inst->frame_rate = 30; ++ ++ init_completion(&inst->irq_done); ++ ++ inst->id = ida_alloc(&inst->dev->inst_ida, GFP_KERNEL); ++ if (inst->id < 0) { ++ dev_warn(inst->dev->dev, "Allocating instance ID, fail: %d\n", inst->id); ++ ret = inst->id; ++ goto cleanup_inst; ++ } ++ ++ wave5_vdi_allocate_sram(inst->dev); ++ ++ return 0; ++ ++cleanup_inst: ++ wave5_cleanup_instance(inst); ++ return ret; ++} ++ ++static int wave5_vpu_enc_release(struct file *filp) ++{ ++ return wave5_vpu_release_device(filp, wave5_vpu_enc_close, "encoder"); ++} ++ ++static const struct v4l2_file_operations wave5_vpu_enc_fops = { ++ .owner = THIS_MODULE, ++ .open = wave5_vpu_open_enc, ++ .release = wave5_vpu_enc_release, ++ .unlocked_ioctl = video_ioctl2, ++ .poll = v4l2_m2m_fop_poll, ++ .mmap = v4l2_m2m_fop_mmap, ++}; ++ ++int wave5_vpu_enc_register_device(struct vpu_device *dev) ++{ ++ struct video_device *vdev_enc; ++ int ret; ++ ++ vdev_enc = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_enc), GFP_KERNEL); ++ if (!vdev_enc) ++ return -ENOMEM; ++ ++ dev->v4l2_m2m_enc_dev = v4l2_m2m_init(&wave5_vpu_enc_m2m_ops); ++ if (IS_ERR(dev->v4l2_m2m_enc_dev)) { ++ ret = PTR_ERR(dev->v4l2_m2m_enc_dev); ++ dev_err(dev->dev, "v4l2_m2m_init, fail: %d\n", ret); ++ return -EINVAL; ++ } ++ ++ dev->video_dev_enc = vdev_enc; ++ ++ strscpy(vdev_enc->name, VPU_ENC_DEV_NAME, sizeof(vdev_enc->name)); ++ vdev_enc->fops = &wave5_vpu_enc_fops; ++ vdev_enc->ioctl_ops = &wave5_vpu_enc_ioctl_ops; ++ vdev_enc->release = video_device_release_empty; ++ vdev_enc->v4l2_dev = &dev->v4l2_dev; ++ vdev_enc->vfl_dir = VFL_DIR_M2M; ++ vdev_enc->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; ++ vdev_enc->lock = &dev->dev_lock; ++ ++ ret = video_register_device(vdev_enc, VFL_TYPE_VIDEO, -1); ++ if (ret) ++ return ret; ++ ++ video_set_drvdata(vdev_enc, dev); ++ ++ return 0; ++} ++ ++void wave5_vpu_enc_unregister_device(struct vpu_device *dev) ++{ ++ video_unregister_device(dev->video_dev_enc); ++ if (dev->v4l2_m2m_enc_dev) ++ v4l2_m2m_release(dev->v4l2_m2m_enc_dev); ++} +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpuerror.h b/drivers/media/platform/chips-media/wave5/wave5-vpuerror.h +--- a/drivers/media/platform/chips-media/wave5/wave5-vpuerror.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vpuerror.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,292 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ ++/* ++ * Wave5 series multi-standard codec IP - error values ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++ ++#ifndef ERROR_CODE_H_INCLUDED ++#define ERROR_CODE_H_INCLUDED ++ ++/* ++ * WAVE5 ++ */ ++ ++/************************************************************************/ ++/* WAVE5 COMMON SYSTEM ERROR (FAIL_REASON) */ ++/************************************************************************/ ++#define WAVE5_SYSERR_QUEUEING_FAIL 0x00000001 ++#define WAVE5_SYSERR_ACCESS_VIOLATION_HW 0x00000040 ++#define WAVE5_SYSERR_BUS_ERROR 0x00000200 ++#define WAVE5_SYSERR_DOUBLE_FAULT 0x00000400 ++#define WAVE5_SYSERR_RESULT_NOT_READY 0x00000800 ++#define WAVE5_SYSERR_VPU_STILL_RUNNING 0x00001000 ++#define WAVE5_SYSERR_UNKNOWN_CMD 0x00002000 ++#define WAVE5_SYSERR_UNKNOWN_CODEC_STD 0x00004000 ++#define WAVE5_SYSERR_UNKNOWN_QUERY_OPTION 0x00008000 ++#define WAVE5_SYSERR_VLC_BUF_FULL 0x00010000 ++#define WAVE5_SYSERR_WATCHDOG_TIMEOUT 0x00020000 ++#define WAVE5_SYSERR_VCPU_TIMEOUT 0x00080000 ++#define WAVE5_SYSERR_TEMP_SEC_BUF_OVERFLOW 0x00200000 ++#define WAVE5_SYSERR_NEED_MORE_TASK_BUF 0x00400000 ++#define WAVE5_SYSERR_PRESCAN_ERR 0x00800000 ++#define WAVE5_SYSERR_ENC_GBIN_OVERCONSUME 0x01000000 ++#define WAVE5_SYSERR_ENC_MAX_ZERO_DETECT 0x02000000 ++#define WAVE5_SYSERR_ENC_LVL_FIRST_ERROR 0x04000000 ++#define WAVE5_SYSERR_ENC_EG_RANGE_OVER 0x08000000 ++#define WAVE5_SYSERR_ENC_IRB_FRAME_DROP 0x10000000 ++#define WAVE5_SYSERR_INPLACE_V 0x20000000 ++#define WAVE5_SYSERR_FATAL_VPU_HANGUP 0xf0000000 ++ ++/************************************************************************/ ++/* WAVE5 COMMAND QUEUE ERROR (FAIL_REASON) */ ++/************************************************************************/ ++#define WAVE5_CMDQ_ERR_NOT_QUEABLE_CMD 0x00000001 ++#define WAVE5_CMDQ_ERR_SKIP_MODE_ENABLE 0x00000002 ++#define WAVE5_CMDQ_ERR_INST_FLUSHING 0x00000003 ++#define WAVE5_CMDQ_ERR_INST_INACTIVE 0x00000004 ++#define WAVE5_CMDQ_ERR_QUEUE_FAIL 0x00000005 ++#define WAVE5_CMDQ_ERR_CMD_BUF_FULL 0x00000006 ++ ++/************************************************************************/ ++/* WAVE5 ERROR ON DECODER (ERR_INFO) */ ++/************************************************************************/ ++// HEVC ++#define HEVC_SPSERR_SEQ_PARAMETER_SET_ID 0x00001000 ++#define HEVC_SPSERR_CHROMA_FORMAT_IDC 0x00001001 ++#define HEVC_SPSERR_PIC_WIDTH_IN_LUMA_SAMPLES 0x00001002 ++#define HEVC_SPSERR_PIC_HEIGHT_IN_LUMA_SAMPLES 0x00001003 ++#define HEVC_SPSERR_CONF_WIN_LEFT_OFFSET 0x00001004 ++#define HEVC_SPSERR_CONF_WIN_RIGHT_OFFSET 0x00001005 ++#define HEVC_SPSERR_CONF_WIN_TOP_OFFSET 0x00001006 ++#define HEVC_SPSERR_CONF_WIN_BOTTOM_OFFSET 0x00001007 ++#define HEVC_SPSERR_BIT_DEPTH_LUMA_MINUS8 0x00001008 ++#define HEVC_SPSERR_BIT_DEPTH_CHROMA_MINUS8 0x00001009 ++#define HEVC_SPSERR_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4 0x0000100A ++#define HEVC_SPSERR_SPS_MAX_DEC_PIC_BUFFERING 0x0000100B ++#define HEVC_SPSERR_SPS_MAX_NUM_REORDER_PICS 0x0000100C ++#define HEVC_SPSERR_SPS_MAX_LATENCY_INCREASE 0x0000100D ++#define HEVC_SPSERR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3 0x0000100E ++#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE 0x0000100F ++#define HEVC_SPSERR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2 0x00001010 ++#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE 0x00001011 ++#define HEVC_SPSERR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER 0x00001012 ++#define HEVC_SPSERR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA 0x00001013 ++#define HEVC_SPSERR_SCALING_LIST 0x00001014 ++#define HEVC_SPSERR_LOG2_DIFF_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3 0x00001015 ++#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE 0x00001016 ++#define HEVC_SPSERR_NUM_SHORT_TERM_REF_PIC_SETS 0x00001017 ++#define HEVC_SPSERR_NUM_LONG_TERM_REF_PICS_SPS 0x00001018 ++#define HEVC_SPSERR_GBU_PARSING_ERROR 0x00001019 ++#define HEVC_SPSERR_EXTENSION_FLAG 0x0000101A ++#define HEVC_SPSERR_VUI_ERROR 0x0000101B ++#define HEVC_SPSERR_ACTIVATE_SPS 0x0000101C ++#define HEVC_SPSERR_PROFILE_SPACE 0x0000101D ++#define HEVC_PPSERR_PPS_PIC_PARAMETER_SET_ID 0x00002000 ++#define HEVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID 0x00002001 ++#define HEVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1 0x00002002 ++#define HEVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1 0x00002003 ++#define HEVC_PPSERR_INIT_QP_MINUS26 0x00002004 ++#define HEVC_PPSERR_DIFF_CU_QP_DELTA_DEPTH 0x00002005 ++#define HEVC_PPSERR_PPS_CB_QP_OFFSET 0x00002006 ++#define HEVC_PPSERR_PPS_CR_QP_OFFSET 0x00002007 ++#define HEVC_PPSERR_NUM_TILE_COLUMNS_MINUS1 0x00002008 ++#define HEVC_PPSERR_NUM_TILE_ROWS_MINUS1 0x00002009 ++#define HEVC_PPSERR_COLUMN_WIDTH_MINUS1 0x0000200A ++#define HEVC_PPSERR_ROW_HEIGHT_MINUS1 0x0000200B ++#define HEVC_PPSERR_PPS_BETA_OFFSET_DIV2 0x0000200C ++#define HEVC_PPSERR_PPS_TC_OFFSET_DIV2 0x0000200D ++#define HEVC_PPSERR_SCALING_LIST 0x0000200E ++#define HEVC_PPSERR_LOG2_PARALLEL_MERGE_LEVEL_MINUS2 0x0000200F ++#define HEVC_PPSERR_NUM_TILE_COLUMNS_RANGE_OUT 0x00002010 ++#define HEVC_PPSERR_NUM_TILE_ROWS_RANGE_OUT 0x00002011 ++#define HEVC_PPSERR_MORE_RBSP_DATA_ERROR 0x00002012 ++#define HEVC_PPSERR_PPS_PIC_PARAMETER_SET_ID_RANGE_OUT 0x00002013 ++#define HEVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID_RANGE_OUT 0x00002014 ++#define HEVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1_RANGE_OUT 0x00002015 ++#define HEVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1_RANGE_OUT 0x00002016 ++#define HEVC_PPSERR_PPS_CB_QP_OFFSET_RANGE_OUT 0x00002017 ++#define HEVC_PPSERR_PPS_CR_QP_OFFSET_RANGE_OUT 0x00002018 ++#define HEVC_PPSERR_COLUMN_WIDTH_MINUS1_RANGE_OUT 0x00002019 ++#define HEVC_PPSERR_ROW_HEIGHT_MINUS1_RANGE_OUT 0x00002020 ++#define HEVC_PPSERR_PPS_BETA_OFFSET_DIV2_RANGE_OUT 0x00002021 ++#define HEVC_PPSERR_PPS_TC_OFFSET_DIV2_RANGE_OUT 0x00002022 ++#define HEVC_SHERR_SLICE_PIC_PARAMETER_SET_ID 0x00003000 ++#define HEVC_SHERR_ACTIVATE_PPS 0x00003001 ++#define HEVC_SHERR_ACTIVATE_SPS 0x00003002 ++#define HEVC_SHERR_SLICE_TYPE 0x00003003 ++#define HEVC_SHERR_FIRST_SLICE_IS_DEPENDENT_SLICE 0x00003004 ++#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET_SPS_FLAG 0x00003005 ++#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET 0x00003006 ++#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET_IDX 0x00003007 ++#define HEVC_SHERR_NUM_LONG_TERM_SPS 0x00003008 ++#define HEVC_SHERR_NUM_LONG_TERM_PICS 0x00003009 ++#define HEVC_SHERR_LT_IDX_SPS_IS_OUT_OF_RANGE 0x0000300A ++#define HEVC_SHERR_DELTA_POC_MSB_CYCLE_LT 0x0000300B ++#define HEVC_SHERR_NUM_REF_IDX_L0_ACTIVE_MINUS1 0x0000300C ++#define HEVC_SHERR_NUM_REF_IDX_L1_ACTIVE_MINUS1 0x0000300D ++#define HEVC_SHERR_COLLOCATED_REF_IDX 0x0000300E ++#define HEVC_SHERR_PRED_WEIGHT_TABLE 0x0000300F ++#define HEVC_SHERR_FIVE_MINUS_MAX_NUM_MERGE_CAND 0x00003010 ++#define HEVC_SHERR_SLICE_QP_DELTA 0x00003011 ++#define HEVC_SHERR_SLICE_QP_DELTA_IS_OUT_OF_RANGE 0x00003012 ++#define HEVC_SHERR_SLICE_CB_QP_OFFSET 0x00003013 ++#define HEVC_SHERR_SLICE_CR_QP_OFFSET 0x00003014 ++#define HEVC_SHERR_SLICE_BETA_OFFSET_DIV2 0x00003015 ++#define HEVC_SHERR_SLICE_TC_OFFSET_DIV2 0x00003016 ++#define HEVC_SHERR_NUM_ENTRY_POINT_OFFSETS 0x00003017 ++#define HEVC_SHERR_OFFSET_LEN_MINUS1 0x00003018 ++#define HEVC_SHERR_SLICE_SEGMENT_HEADER_EXTENSION_LENGTH 0x00003019 ++#define HEVC_SHERR_WRONG_POC_IN_STILL_PICTURE_PROFILE 0x0000301A ++#define HEVC_SHERR_SLICE_TYPE_ERROR_IN_STILL_PICTURE_PROFILE 0x0000301B ++#define HEVC_SHERR_PPS_ID_NOT_EQUAL_PREV_VALUE 0x0000301C ++#define HEVC_SPECERR_OVER_PICTURE_WIDTH_SIZE 0x00004000 ++#define HEVC_SPECERR_OVER_PICTURE_HEIGHT_SIZE 0x00004001 ++#define HEVC_SPECERR_OVER_CHROMA_FORMAT 0x00004002 ++#define HEVC_SPECERR_OVER_BIT_DEPTH 0x00004003 ++#define HEVC_SPECERR_OVER_BUFFER_OVER_FLOW 0x00004004 ++#define HEVC_SPECERR_OVER_WRONG_BUFFER_ACCESS 0x00004005 ++#define HEVC_ETCERR_INIT_SEQ_SPS_NOT_FOUND 0x00005000 ++#define HEVC_ETCERR_DEC_PIC_VCL_NOT_FOUND 0x00005001 ++#define HEVC_ETCERR_NO_VALID_SLICE_IN_AU 0x00005002 ++#define HEVC_ETCERR_INPLACE_V 0x0000500F ++ ++// AVC ++#define AVC_SPSERR_SEQ_PARAMETER_SET_ID 0x00001000 ++#define AVC_SPSERR_CHROMA_FORMAT_IDC 0x00001001 ++#define AVC_SPSERR_PIC_WIDTH_IN_LUMA_SAMPLES 0x00001002 ++#define AVC_SPSERR_PIC_HEIGHT_IN_LUMA_SAMPLES 0x00001003 ++#define AVC_SPSERR_CONF_WIN_LEFT_OFFSET 0x00001004 ++#define AVC_SPSERR_CONF_WIN_RIGHT_OFFSET 0x00001005 ++#define AVC_SPSERR_CONF_WIN_TOP_OFFSET 0x00001006 ++#define AVC_SPSERR_CONF_WIN_BOTTOM_OFFSET 0x00001007 ++#define AVC_SPSERR_BIT_DEPTH_LUMA_MINUS8 0x00001008 ++#define AVC_SPSERR_BIT_DEPTH_CHROMA_MINUS8 0x00001009 ++#define AVC_SPSERR_SPS_MAX_DEC_PIC_BUFFERING 0x0000100B ++#define AVC_SPSERR_SPS_MAX_NUM_REORDER_PICS 0x0000100C ++#define AVC_SPSERR_SCALING_LIST 0x00001014 ++#define AVC_SPSERR_GBU_PARSING_ERROR 0x00001019 ++#define AVC_SPSERR_VUI_ERROR 0x0000101B ++#define AVC_SPSERR_ACTIVATE_SPS 0x0000101C ++#define AVC_PPSERR_PPS_PIC_PARAMETER_SET_ID 0x00002000 ++#define AVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID 0x00002001 ++#define AVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1 0x00002002 ++#define AVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1 0x00002003 ++#define AVC_PPSERR_INIT_QP_MINUS26 0x00002004 ++#define AVC_PPSERR_PPS_CB_QP_OFFSET 0x00002006 ++#define AVC_PPSERR_PPS_CR_QP_OFFSET 0x00002007 ++#define AVC_PPSERR_SCALING_LIST 0x0000200E ++#define AVC_PPSERR_MORE_RBSP_DATA_ERROR 0x00002012 ++#define AVC_PPSERR_PPS_PIC_PARAMETER_SET_ID_RANGE_OUT 0x00002013 ++#define AVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID_RANGE_OUT 0x00002014 ++#define AVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1_RANGE_OUT 0x00002015 ++#define AVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1_RANGE_OUT 0x00002016 ++#define AVC_PPSERR_PPS_CB_QP_OFFSET_RANGE_OUT 0x00002017 ++#define AVC_PPSERR_PPS_CR_QP_OFFSET_RANGE_OUT 0x00002018 ++#define AVC_SHERR_SLICE_PIC_PARAMETER_SET_ID 0x00003000 ++#define AVC_SHERR_ACTIVATE_PPS 0x00003001 ++#define AVC_SHERR_ACTIVATE_SPS 0x00003002 ++#define AVC_SHERR_SLICE_TYPE 0x00003003 ++#define AVC_SHERR_FIRST_MB_IN_SLICE 0x00003004 ++#define AVC_SHERR_RPLM 0x00003006 ++#define AVC_SHERR_LT_IDX_SPS_IS_OUT_OF_RANGE 0x0000300A ++#define AVC_SHERR_NUM_REF_IDX_L0_ACTIVE_MINUS1 0x0000300C ++#define AVC_SHERR_NUM_REF_IDX_L1_ACTIVE_MINUS1 0x0000300D ++#define AVC_SHERR_PRED_WEIGHT_TABLE 0x0000300F ++#define AVC_SHERR_SLICE_QP_DELTA 0x00003011 ++#define AVC_SHERR_SLICE_BETA_OFFSET_DIV2 0x00003015 ++#define AVC_SHERR_SLICE_TC_OFFSET_DIV2 0x00003016 ++#define AVC_SHERR_DISABLE_DEBLOCK_FILTER_IDC 0x00003017 ++#define AVC_SPECERR_OVER_PICTURE_WIDTH_SIZE 0x00004000 ++#define AVC_SPECERR_OVER_PICTURE_HEIGHT_SIZE 0x00004001 ++#define AVC_SPECERR_OVER_CHROMA_FORMAT 0x00004002 ++#define AVC_SPECERR_OVER_BIT_DEPTH 0x00004003 ++#define AVC_SPECERR_OVER_BUFFER_OVER_FLOW 0x00004004 ++#define AVC_SPECERR_OVER_WRONG_BUFFER_ACCESS 0x00004005 ++#define AVC_ETCERR_INIT_SEQ_SPS_NOT_FOUND 0x00005000 ++#define AVC_ETCERR_DEC_PIC_VCL_NOT_FOUND 0x00005001 ++#define AVC_ETCERR_NO_VALID_SLICE_IN_AU 0x00005002 ++#define AVC_ETCERR_ASO 0x00005004 ++#define AVC_ETCERR_FMO 0x00005005 ++#define AVC_ETCERR_INPLACE_V 0x0000500F ++ ++/************************************************************************/ ++/* WAVE5 WARNING ON DECODER (WARN_INFO) */ ++/************************************************************************/ ++// HEVC ++#define HEVC_SPSWARN_MAX_SUB_LAYERS_MINUS1 0x00000001 ++#define HEVC_SPSWARN_GENERAL_RESERVED_ZERO_44BITS 0x00000002 ++#define HEVC_SPSWARN_RESERVED_ZERO_2BITS 0x00000004 ++#define HEVC_SPSWARN_SUB_LAYER_RESERVED_ZERO_44BITS 0x00000008 ++#define HEVC_SPSWARN_GENERAL_LEVEL_IDC 0x00000010 ++#define HEVC_SPSWARN_SPS_MAX_DEC_PIC_BUFFERING_VALUE_OVER 0x00000020 ++#define HEVC_SPSWARN_RBSP_TRAILING_BITS 0x00000040 ++#define HEVC_SPSWARN_ST_RPS_UE_ERROR 0x00000080 ++#define HEVC_SPSWARN_EXTENSION_FLAG 0x01000000 ++#define HEVC_SPSWARN_REPLACED_WITH_PREV_SPS 0x02000000 ++#define HEVC_PPSWARN_RBSP_TRAILING_BITS 0x00000100 ++#define HEVC_PPSWARN_REPLACED_WITH_PREV_PPS 0x00000200 ++#define HEVC_SHWARN_FIRST_SLICE_SEGMENT_IN_PIC_FLAG 0x00001000 ++#define HEVC_SHWARN_NO_OUTPUT_OF_PRIOR_PICS_FLAG 0x00002000 ++#define HEVC_SHWARN_PIC_OUTPUT_FLAG 0x00004000 ++#define HEVC_SHWARN_DUPLICATED_SLICE_SEGMENT 0x00008000 ++#define HEVC_ETCWARN_INIT_SEQ_VCL_NOT_FOUND 0x00010000 ++#define HEVC_ETCWARN_MISSING_REFERENCE_PICTURE 0x00020000 ++#define HEVC_ETCWARN_WRONG_TEMPORAL_ID 0x00040000 ++#define HEVC_ETCWARN_ERROR_PICTURE_IS_REFERENCED 0x00080000 ++#define HEVC_SPECWARN_OVER_PROFILE 0x00100000 ++#define HEVC_SPECWARN_OVER_LEVEL 0x00200000 ++#define HEVC_PRESWARN_PARSING_ERR 0x04000000 ++#define HEVC_PRESWARN_MVD_OUT_OF_RANGE 0x08000000 ++#define HEVC_PRESWARN_CU_QP_DELTA_VAL_OUT_OF_RANGE 0x09000000 ++#define HEVC_PRESWARN_COEFF_LEVEL_REMAINING_OUT_OF_RANGE 0x0A000000 ++#define HEVC_PRESWARN_PCM_ERR 0x0B000000 ++#define HEVC_PRESWARN_OVERCONSUME 0x0C000000 ++#define HEVC_PRESWARN_END_OF_SUBSET_ONE_BIT_ERR 0x10000000 ++#define HEVC_PRESWARN_END_OF_SLICE_SEGMENT_FLAG 0x20000000 ++ ++// AVC ++#define AVC_SPSWARN_RESERVED_ZERO_2BITS 0x00000004 ++#define AVC_SPSWARN_GENERAL_LEVEL_IDC 0x00000010 ++#define AVC_SPSWARN_RBSP_TRAILING_BITS 0x00000040 ++#define AVC_PPSWARN_RBSP_TRAILING_BITS 0x00000100 ++#define AVC_SHWARN_NO_OUTPUT_OF_PRIOR_PICS_FLAG 0x00002000 ++#define AVC_ETCWARN_INIT_SEQ_VCL_NOT_FOUND 0x00010000 ++#define AVC_ETCWARN_MISSING_REFERENCE_PICTURE 0x00020000 ++#define AVC_ETCWARN_ERROR_PICTURE_IS_REFERENCED 0x00080000 ++#define AVC_SPECWARN_OVER_PROFILE 0x00100000 ++#define AVC_SPECWARN_OVER_LEVEL 0x00200000 ++#define AVC_PRESWARN_MVD_RANGE_OUT 0x00400000 ++#define AVC_PRESWARN_MB_QPD_RANGE_OUT 0x00500000 ++#define AVC_PRESWARN_COEFF_RANGE_OUT 0x00600000 ++#define AVC_PRESWARN_MV_RANGE_OUT 0x00700000 ++#define AVC_PRESWARN_MB_SKIP_RUN_RANGE_OUT 0x00800000 ++#define AVC_PRESWARN_MB_TYPE_RANGE_OUT 0x00900000 ++#define AVC_PRESWARN_SUB_MB_TYPE_RANGE_OUT 0x00A00000 ++#define AVC_PRESWARN_CBP_RANGE_OUT 0x00B00000 ++#define AVC_PRESWARN_INTRA_CHROMA_PRED_MODE_RANGE_OUT 0x00C00000 ++#define AVC_PRESWARN_REF_IDX_RANGE_OUT 0x00D00000 ++#define AVC_PRESWARN_COEFF_TOKEN_RANGE_OUT 0x00E00000 ++#define AVC_PRESWARN_TOTAL_ZERO_RANGE_OUT 0x00F00000 ++#define AVC_PRESWARN_RUN_BEFORE_RANGE_OUT 0x01000000 ++#define AVC_PRESWARN_OVERCONSUME 0x01100000 ++#define AVC_PRESWARN_MISSING_SLICE 0x01200000 ++ ++/************************************************************************/ ++/* WAVE5 ERROR ON ENCODER (ERR_INFO) */ ++/************************************************************************/ ++ ++/************************************************************************/ ++/* WAVE5 WARNING ON ENCODER (WARN_INFO) */ ++/************************************************************************/ ++#define WAVE5_ETCWARN_FORCED_SPLIT_BY_CU8X8 0x000000001 ++ ++/************************************************************************/ ++/* WAVE5 debug info (PRI_REASON) */ ++/************************************************************************/ ++#define WAVE5_DEC_VCORE_VCE_HANGUP 0x0001 ++#define WAVE5_DEC_VCORE_UNDETECTED_SYNTAX_ERR 0x0002 ++#define WAVE5_DEC_VCORE_MIB_BUSY 0x0003 ++#define WAVE5_DEC_VCORE_VLC_BUSY 0x0004 ++ ++#endif /* ERROR_CODE_H_INCLUDED */ +diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpu.h b/drivers/media/platform/chips-media/wave5/wave5-vpu.h +--- a/drivers/media/platform/chips-media/wave5/wave5-vpu.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.h 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,83 @@ ++/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ ++/* ++ * Wave5 series multi-standard codec IP - basic types ++ * ++ * Copyright (C) 2021-2023 CHIPS&MEDIA INC ++ */ ++#ifndef __VPU_DRV_H__ ++#define __VPU_DRV_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "wave5-vpuconfig.h" ++#include "wave5-vpuapi.h" ++ ++#define VPU_BUF_SYNC_TO_DEVICE 0 ++#define VPU_BUF_SYNC_FROM_DEVICE 1 ++ ++struct vpu_src_buffer { ++ struct v4l2_m2m_buffer v4l2_m2m_buf; ++ struct list_head list; ++ bool consumed; ++}; ++ ++struct vpu_dst_buffer { ++ struct v4l2_m2m_buffer v4l2_m2m_buf; ++ bool display; ++}; ++ ++enum vpu_fmt_type { ++ VPU_FMT_TYPE_CODEC = 0, ++ VPU_FMT_TYPE_RAW = 1 ++}; ++ ++struct vpu_format { ++ unsigned int v4l2_pix_fmt; ++ unsigned int max_width; ++ unsigned int min_width; ++ unsigned int max_height; ++ unsigned int min_height; ++}; ++ ++static inline struct vpu_instance *wave5_to_vpu_inst(struct v4l2_fh *vfh) ++{ ++ return container_of(vfh, struct vpu_instance, v4l2_fh); ++} ++ ++static inline struct vpu_instance *wave5_ctrl_to_vpu_inst(struct v4l2_ctrl *vctrl) ++{ ++ return container_of(vctrl->handler, struct vpu_instance, v4l2_ctrl_hdl); ++} ++ ++static inline struct vpu_src_buffer *wave5_to_vpu_src_buf(struct vb2_v4l2_buffer *vbuf) ++{ ++ return container_of(vbuf, struct vpu_src_buffer, v4l2_m2m_buf.vb); ++} ++ ++static inline struct vpu_dst_buffer *wave5_to_vpu_dst_buf(struct vb2_v4l2_buffer *vbuf) ++{ ++ return container_of(vbuf, struct vpu_dst_buffer, v4l2_m2m_buf.vb); ++} ++ ++int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout); ++ ++int wave5_vpu_dec_register_device(struct vpu_device *dev); ++void wave5_vpu_dec_unregister_device(struct vpu_device *dev); ++int wave5_vpu_enc_register_device(struct vpu_device *dev); ++void wave5_vpu_enc_unregister_device(struct vpu_device *dev); ++static inline bool wave5_vpu_both_queues_are_streaming(struct vpu_instance *inst) ++{ ++ struct vb2_queue *vq_cap = ++ v4l2_m2m_get_vq(inst->v4l2_fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); ++ struct vb2_queue *vq_out = ++ v4l2_m2m_get_vq(inst->v4l2_fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); ++ ++ return vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out); ++} ++ ++#endif +diff -Naur --no-dereference a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c +--- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,1180 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * TI CSI2RX Shim Wrapper Driver ++ * ++ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ ++ * ++ * Author: Pratyush Yadav ++ * Author: Jai Luthra ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define TI_CSI2RX_MODULE_NAME "j721e-csi2rx" ++ ++#define SHIM_CNTL 0x10 ++#define SHIM_CNTL_PIX_RST BIT(0) ++ ++#define SHIM_DMACNTX 0x20 ++#define SHIM_DMACNTX_EN BIT(31) ++#define SHIM_DMACNTX_YUV422 GENMASK(27, 26) ++#define SHIM_DMACNTX_SIZE GENMASK(21, 20) ++#define SHIM_DMACNTX_FMT GENMASK(5, 0) ++#define SHIM_DMACNTX_YUV422_MODE_11 3 ++#define SHIM_DMACNTX_SIZE_8 0 ++#define SHIM_DMACNTX_SIZE_16 1 ++#define SHIM_DMACNTX_SIZE_32 2 ++ ++#define SHIM_PSI_CFG0 0x24 ++#define SHIM_PSI_CFG0_SRC_TAG GENMASK(15, 0) ++#define SHIM_PSI_CFG0_DST_TAG GENMASK(31, 16) ++ ++#define PSIL_WORD_SIZE_BYTES 16 ++/* ++ * There are no hard limits on the width or height. The DMA engine can handle ++ * all sizes. The max width and height are arbitrary numbers for this driver. ++ * Use 16K * 16K as the arbitrary limit. It is large enough that it is unlikely ++ * the limit will be hit in practice. ++ */ ++#define MAX_WIDTH_BYTES SZ_16K ++#define MAX_HEIGHT_LINES SZ_16K ++ ++#define DRAIN_TIMEOUT_MS 50 ++#define DRAIN_BUFFER_SIZE SZ_32K ++ ++struct ti_csi2rx_fmt { ++ u32 fourcc; /* Four character code. */ ++ u32 code; /* Mbus code. */ ++ u32 csi_dt; /* CSI Data type. */ ++ u8 bpp; /* Bits per pixel. */ ++ u8 size; /* Data size shift when unpacking. */ ++}; ++ ++struct ti_csi2rx_buffer { ++ /* Common v4l2 buffer. Must be first. */ ++ struct vb2_v4l2_buffer vb; ++ struct list_head list; ++ struct ti_csi2rx_dev *csi; ++}; ++ ++enum ti_csi2rx_dma_state { ++ TI_CSI2RX_DMA_STOPPED, /* Streaming not started yet. */ ++ TI_CSI2RX_DMA_IDLE, /* Streaming but no pending DMA operation. */ ++ TI_CSI2RX_DMA_ACTIVE, /* Streaming and pending DMA operation. */ ++}; ++ ++struct ti_csi2rx_dma { ++ /* Protects all fields in this struct. */ ++ spinlock_t lock; ++ struct dma_chan *chan; ++ /* Buffers queued to the driver, waiting to be processed by DMA. */ ++ struct list_head queue; ++ enum ti_csi2rx_dma_state state; ++ /* ++ * Queue of buffers submitted to DMA engine. ++ */ ++ struct list_head submitted; ++ /* Buffer to drain stale data from PSI-L endpoint */ ++ struct { ++ void *vaddr; ++ dma_addr_t paddr; ++ size_t len; ++ } drain; ++}; ++ ++struct ti_csi2rx_dev { ++ struct device *dev; ++ void __iomem *shim; ++ struct v4l2_device v4l2_dev; ++ struct video_device vdev; ++ struct media_device mdev; ++ struct media_pipeline pipe; ++ struct media_pad pad; ++ struct v4l2_async_notifier notifier; ++ struct v4l2_subdev *source; ++ struct vb2_queue vidq; ++ struct mutex mutex; /* To serialize ioctls. */ ++ struct v4l2_format v_fmt; ++ struct ti_csi2rx_dma dma; ++ u32 sequence; ++}; ++ ++static const struct ti_csi2rx_fmt ti_csi2rx_formats[] = { ++ { ++ .fourcc = V4L2_PIX_FMT_YUYV, ++ .code = MEDIA_BUS_FMT_YUYV8_1X16, ++ .csi_dt = MIPI_CSI2_DT_YUV422_8B, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_UYVY, ++ .code = MEDIA_BUS_FMT_UYVY8_1X16, ++ .csi_dt = MIPI_CSI2_DT_YUV422_8B, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_YVYU, ++ .code = MEDIA_BUS_FMT_YVYU8_1X16, ++ .csi_dt = MIPI_CSI2_DT_YUV422_8B, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_VYUY, ++ .code = MEDIA_BUS_FMT_VYUY8_1X16, ++ .csi_dt = MIPI_CSI2_DT_YUV422_8B, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_SBGGR8, ++ .code = MEDIA_BUS_FMT_SBGGR8_1X8, ++ .csi_dt = MIPI_CSI2_DT_RAW8, ++ .bpp = 8, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_SGBRG8, ++ .code = MEDIA_BUS_FMT_SGBRG8_1X8, ++ .csi_dt = MIPI_CSI2_DT_RAW8, ++ .bpp = 8, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_SGRBG8, ++ .code = MEDIA_BUS_FMT_SGRBG8_1X8, ++ .csi_dt = MIPI_CSI2_DT_RAW8, ++ .bpp = 8, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_SRGGB8, ++ .code = MEDIA_BUS_FMT_SRGGB8_1X8, ++ .csi_dt = MIPI_CSI2_DT_RAW8, ++ .bpp = 8, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_GREY, ++ .code = MEDIA_BUS_FMT_Y8_1X8, ++ .csi_dt = MIPI_CSI2_DT_RAW8, ++ .bpp = 8, ++ .size = SHIM_DMACNTX_SIZE_8, ++ }, { ++ .fourcc = V4L2_PIX_FMT_SBGGR10, ++ .code = MEDIA_BUS_FMT_SBGGR10_1X10, ++ .csi_dt = MIPI_CSI2_DT_RAW10, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_16, ++ }, { ++ .fourcc = V4L2_PIX_FMT_SGBRG10, ++ .code = MEDIA_BUS_FMT_SGBRG10_1X10, ++ .csi_dt = MIPI_CSI2_DT_RAW10, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_16, ++ }, { ++ .fourcc = V4L2_PIX_FMT_SGRBG10, ++ .code = MEDIA_BUS_FMT_SGRBG10_1X10, ++ .csi_dt = MIPI_CSI2_DT_RAW10, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_16, ++ }, { ++ .fourcc = V4L2_PIX_FMT_SRGGB10, ++ .code = MEDIA_BUS_FMT_SRGGB10_1X10, ++ .csi_dt = MIPI_CSI2_DT_RAW10, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_16, ++ }, { ++ .fourcc = V4L2_PIX_FMT_RGB565X, ++ .code = MEDIA_BUS_FMT_RGB565_1X16, ++ .csi_dt = MIPI_CSI2_DT_RGB565, ++ .bpp = 16, ++ .size = SHIM_DMACNTX_SIZE_16, ++ }, { ++ .fourcc = V4L2_PIX_FMT_XBGR32, ++ .code = MEDIA_BUS_FMT_RGB888_1X24, ++ .csi_dt = MIPI_CSI2_DT_RGB888, ++ .bpp = 32, ++ .size = SHIM_DMACNTX_SIZE_32, ++ }, { ++ .fourcc = V4L2_PIX_FMT_RGBX32, ++ .code = MEDIA_BUS_FMT_BGR888_1X24, ++ .csi_dt = MIPI_CSI2_DT_RGB888, ++ .bpp = 32, ++ .size = SHIM_DMACNTX_SIZE_32, ++ }, ++ ++ /* More formats can be supported but they are not listed for now. */ ++}; ++ ++/* Forward declaration needed by ti_csi2rx_dma_callback. */ ++static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi, ++ struct ti_csi2rx_buffer *buf); ++ ++static const struct ti_csi2rx_fmt *find_format_by_fourcc(u32 pixelformat) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ti_csi2rx_formats); i++) { ++ if (ti_csi2rx_formats[i].fourcc == pixelformat) ++ return &ti_csi2rx_formats[i]; ++ } ++ ++ return NULL; ++} ++ ++static const struct ti_csi2rx_fmt *find_format_by_code(u32 code) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ti_csi2rx_formats); i++) { ++ if (ti_csi2rx_formats[i].code == code) ++ return &ti_csi2rx_formats[i]; ++ } ++ ++ return NULL; ++} ++ ++static void ti_csi2rx_fill_fmt(const struct ti_csi2rx_fmt *csi_fmt, ++ struct v4l2_format *v4l2_fmt) ++{ ++ struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix; ++ unsigned int pixels_in_word; ++ ++ pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / csi_fmt->bpp; ++ ++ /* Clamp width and height to sensible maximums (16K x 16K) */ ++ pix->width = clamp_t(unsigned int, pix->width, ++ pixels_in_word, ++ MAX_WIDTH_BYTES * 8 / csi_fmt->bpp); ++ pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES); ++ ++ /* Width should be a multiple of transfer word-size */ ++ pix->width = rounddown(pix->width, pixels_in_word); ++ ++ v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ pix->pixelformat = csi_fmt->fourcc; ++ pix->bytesperline = pix->width * (csi_fmt->bpp / 8); ++ pix->sizeimage = pix->bytesperline * pix->height; ++} ++ ++static int ti_csi2rx_querycap(struct file *file, void *priv, ++ struct v4l2_capability *cap) ++{ ++ strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver)); ++ strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card)); ++ ++ return 0; ++} ++ ++static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_fmtdesc *f) ++{ ++ const struct ti_csi2rx_fmt *fmt = NULL; ++ ++ if (f->mbus_code) { ++ /* 1-to-1 mapping between bus formats and pixel formats */ ++ if (f->index > 0) ++ return -EINVAL; ++ ++ fmt = find_format_by_code(f->mbus_code); ++ } else { ++ if (f->index >= ARRAY_SIZE(ti_csi2rx_formats)) ++ return -EINVAL; ++ ++ fmt = &ti_csi2rx_formats[f->index]; ++ } ++ ++ if (!fmt) ++ return -EINVAL; ++ ++ f->pixelformat = fmt->fourcc; ++ memset(f->reserved, 0, sizeof(f->reserved)); ++ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ return 0; ++} ++ ++static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov, ++ struct v4l2_format *f) ++{ ++ struct ti_csi2rx_dev *csi = video_drvdata(file); ++ ++ *f = csi->v_fmt; ++ ++ return 0; ++} ++ ++static int ti_csi2rx_try_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ const struct ti_csi2rx_fmt *fmt; ++ ++ /* ++ * Default to the first format if the requested pixel format code isn't ++ * supported. ++ */ ++ fmt = find_format_by_fourcc(f->fmt.pix.pixelformat); ++ if (!fmt) ++ fmt = &ti_csi2rx_formats[0]; ++ ++ /* Interlaced formats are not supported. */ ++ f->fmt.pix.field = V4L2_FIELD_NONE; ++ ++ ti_csi2rx_fill_fmt(fmt, f); ++ ++ return 0; ++} ++ ++static int ti_csi2rx_s_fmt_vid_cap(struct file *file, void *priv, ++ struct v4l2_format *f) ++{ ++ struct ti_csi2rx_dev *csi = video_drvdata(file); ++ struct vb2_queue *q = &csi->vidq; ++ int ret; ++ ++ if (vb2_is_busy(q)) ++ return -EBUSY; ++ ++ ret = ti_csi2rx_try_fmt_vid_cap(file, priv, f); ++ if (ret < 0) ++ return ret; ++ ++ csi->v_fmt = *f; ++ ++ return 0; ++} ++ ++static int ti_csi2rx_enum_framesizes(struct file *file, void *fh, ++ struct v4l2_frmsizeenum *fsize) ++{ ++ const struct ti_csi2rx_fmt *fmt; ++ unsigned int pixels_in_word; ++ ++ fmt = find_format_by_fourcc(fsize->pixel_format); ++ if (!fmt || fsize->index != 0) ++ return -EINVAL; ++ ++ /* ++ * Number of pixels in one PSI-L word. The transfer happens in multiples ++ * of PSI-L word sizes. ++ */ ++ pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / fmt->bpp; ++ ++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; ++ fsize->stepwise.min_width = pixels_in_word; ++ fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / fmt->bpp, ++ pixels_in_word); ++ fsize->stepwise.step_width = pixels_in_word; ++ fsize->stepwise.min_height = 1; ++ fsize->stepwise.max_height = MAX_HEIGHT_LINES; ++ fsize->stepwise.step_height = 1; ++ ++ return 0; ++} ++ ++static const struct v4l2_ioctl_ops csi_ioctl_ops = { ++ .vidioc_querycap = ti_csi2rx_querycap, ++ .vidioc_enum_fmt_vid_cap = ti_csi2rx_enum_fmt_vid_cap, ++ .vidioc_try_fmt_vid_cap = ti_csi2rx_try_fmt_vid_cap, ++ .vidioc_g_fmt_vid_cap = ti_csi2rx_g_fmt_vid_cap, ++ .vidioc_s_fmt_vid_cap = ti_csi2rx_s_fmt_vid_cap, ++ .vidioc_enum_framesizes = ti_csi2rx_enum_framesizes, ++ .vidioc_reqbufs = vb2_ioctl_reqbufs, ++ .vidioc_create_bufs = vb2_ioctl_create_bufs, ++ .vidioc_prepare_buf = vb2_ioctl_prepare_buf, ++ .vidioc_querybuf = vb2_ioctl_querybuf, ++ .vidioc_qbuf = vb2_ioctl_qbuf, ++ .vidioc_dqbuf = vb2_ioctl_dqbuf, ++ .vidioc_expbuf = vb2_ioctl_expbuf, ++ .vidioc_streamon = vb2_ioctl_streamon, ++ .vidioc_streamoff = vb2_ioctl_streamoff, ++}; ++ ++static const struct v4l2_file_operations csi_fops = { ++ .owner = THIS_MODULE, ++ .open = v4l2_fh_open, ++ .release = vb2_fop_release, ++ .read = vb2_fop_read, ++ .poll = vb2_fop_poll, ++ .unlocked_ioctl = video_ioctl2, ++ .mmap = vb2_fop_mmap, ++}; ++ ++static int csi_async_notifier_bound(struct v4l2_async_notifier *notifier, ++ struct v4l2_subdev *subdev, ++ struct v4l2_async_connection *asc) ++{ ++ struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev); ++ ++ csi->source = subdev; ++ ++ return 0; ++} ++ ++static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier) ++{ ++ struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev); ++ struct video_device *vdev = &csi->vdev; ++ int ret; ++ ++ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); ++ if (ret) ++ return ret; ++ ++ ret = v4l2_create_fwnode_links_to_pad(csi->source, &csi->pad, ++ MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); ++ ++ if (ret) { ++ video_unregister_device(vdev); ++ return ret; ++ } ++ ++ ret = v4l2_device_register_subdev_nodes(&csi->v4l2_dev); ++ if (ret) ++ video_unregister_device(vdev); ++ ++ return ret; ++} ++ ++static const struct v4l2_async_notifier_operations csi_async_notifier_ops = { ++ .bound = csi_async_notifier_bound, ++ .complete = csi_async_notifier_complete, ++}; ++ ++static int ti_csi2rx_notifier_register(struct ti_csi2rx_dev *csi) ++{ ++ struct fwnode_handle *fwnode; ++ struct v4l2_async_connection *asc; ++ struct device_node *node; ++ int ret; ++ ++ node = of_get_child_by_name(csi->dev->of_node, "csi-bridge"); ++ if (!node) ++ return -EINVAL; ++ ++ fwnode = of_fwnode_handle(node); ++ if (!fwnode) { ++ of_node_put(node); ++ return -EINVAL; ++ } ++ ++ v4l2_async_nf_init(&csi->notifier, &csi->v4l2_dev); ++ csi->notifier.ops = &csi_async_notifier_ops; ++ ++ asc = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode, ++ struct v4l2_async_connection); ++ of_node_put(node); ++ if (IS_ERR(asc)) { ++ v4l2_async_nf_cleanup(&csi->notifier); ++ return PTR_ERR(asc); ++ } ++ ++ ret = v4l2_async_nf_register(&csi->notifier); ++ if (ret) { ++ v4l2_async_nf_cleanup(&csi->notifier); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void ti_csi2rx_setup_shim(struct ti_csi2rx_dev *csi) ++{ ++ const struct ti_csi2rx_fmt *fmt; ++ unsigned int reg; ++ ++ fmt = find_format_by_fourcc(csi->v_fmt.fmt.pix.pixelformat); ++ ++ /* De-assert the pixel interface reset. */ ++ reg = SHIM_CNTL_PIX_RST; ++ writel(reg, csi->shim + SHIM_CNTL); ++ ++ reg = SHIM_DMACNTX_EN; ++ reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt); ++ ++ /* ++ * The hardware assumes incoming YUV422 8-bit data on MIPI CSI2 bus ++ * follows the spec and is packed in the order U0 -> Y0 -> V0 -> Y1 -> ++ * ... ++ * ++ * There is an option to swap the bytes around before storing in ++ * memory, to achieve different pixel formats: ++ * ++ * Byte3 <----------- Byte0 ++ * [ Y1 ][ V0 ][ Y0 ][ U0 ] MODE 11 ++ * [ Y1 ][ U0 ][ Y0 ][ V0 ] MODE 10 ++ * [ V0 ][ Y1 ][ U0 ][ Y0 ] MODE 01 ++ * [ U0 ][ Y1 ][ V0 ][ Y0 ] MODE 00 ++ * ++ * We don't have any requirement to change pixelformat from what is ++ * coming from the source, so we keep it in MODE 11, which does not ++ * swap any bytes when storing in memory. ++ */ ++ switch (fmt->fourcc) { ++ case V4L2_PIX_FMT_UYVY: ++ case V4L2_PIX_FMT_VYUY: ++ case V4L2_PIX_FMT_YUYV: ++ case V4L2_PIX_FMT_YVYU: ++ reg |= FIELD_PREP(SHIM_DMACNTX_YUV422, ++ SHIM_DMACNTX_YUV422_MODE_11); ++ break; ++ default: ++ /* Ignore if not YUV 4:2:2 */ ++ break; ++ } ++ ++ reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size); ++ ++ writel(reg, csi->shim + SHIM_DMACNTX); ++ ++ reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) | ++ FIELD_PREP(SHIM_PSI_CFG0_DST_TAG, 0); ++ writel(reg, csi->shim + SHIM_PSI_CFG0); ++} ++ ++static void ti_csi2rx_drain_callback(void *param) ++{ ++ struct completion *drain_complete = param; ++ ++ complete(drain_complete); ++} ++ ++/* ++ * Drain the stale data left at the PSI-L endpoint. ++ * ++ * This might happen if no buffers are queued in time but source is still ++ * streaming. In multi-stream scenarios this can happen when one stream is ++ * stopped but other is still streaming, and thus module-level pixel reset is ++ * not asserted. ++ * ++ * To prevent that stale data corrupting the subsequent transactions, it is ++ * required to issue DMA requests to drain it out. ++ */ ++static int ti_csi2rx_drain_dma(struct ti_csi2rx_dev *csi) ++{ ++ struct dma_async_tx_descriptor *desc; ++ struct completion drain_complete; ++ dma_cookie_t cookie; ++ int ret; ++ ++ init_completion(&drain_complete); ++ ++ desc = dmaengine_prep_slave_single(csi->dma.chan, csi->dma.drain.paddr, ++ csi->dma.drain.len, DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!desc) { ++ ret = -EIO; ++ goto out; ++ } ++ ++ desc->callback = ti_csi2rx_drain_callback; ++ desc->callback_param = &drain_complete; ++ ++ cookie = dmaengine_submit(desc); ++ ret = dma_submit_error(cookie); ++ if (ret) ++ goto out; ++ ++ dma_async_issue_pending(csi->dma.chan); ++ ++ if (!wait_for_completion_timeout(&drain_complete, ++ msecs_to_jiffies(DRAIN_TIMEOUT_MS))) { ++ dmaengine_terminate_sync(csi->dma.chan); ++ dev_dbg(csi->dev, "DMA transfer timed out for drain buffer\n"); ++ ret = -ETIMEDOUT; ++ goto out; ++ } ++out: ++ return ret; ++} ++ ++static void ti_csi2rx_dma_callback(void *param) ++{ ++ struct ti_csi2rx_buffer *buf = param; ++ struct ti_csi2rx_dev *csi = buf->csi; ++ struct ti_csi2rx_dma *dma = &csi->dma; ++ unsigned long flags; ++ ++ /* ++ * TODO: Derive the sequence number from the CSI2RX frame number ++ * hardware monitor registers. ++ */ ++ buf->vb.vb2_buf.timestamp = ktime_get_ns(); ++ buf->vb.sequence = csi->sequence++; ++ ++ spin_lock_irqsave(&dma->lock, flags); ++ ++ WARN_ON(!list_is_first(&buf->list, &dma->submitted)); ++ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); ++ list_del(&buf->list); ++ ++ /* If there are more buffers to process then start their transfer. */ ++ while (!list_empty(&dma->queue)) { ++ buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list); ++ ++ if (ti_csi2rx_start_dma(csi, buf)) { ++ dev_err(csi->dev, "Failed to queue the next buffer for DMA\n"); ++ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); ++ } else { ++ list_move_tail(&buf->list, &dma->submitted); ++ } ++ } ++ ++ if (list_empty(&dma->submitted)) ++ dma->state = TI_CSI2RX_DMA_IDLE; ++ ++ spin_unlock_irqrestore(&dma->lock, flags); ++} ++ ++static int ti_csi2rx_start_dma(struct ti_csi2rx_dev *csi, ++ struct ti_csi2rx_buffer *buf) ++{ ++ unsigned long addr; ++ struct dma_async_tx_descriptor *desc; ++ size_t len = csi->v_fmt.fmt.pix.sizeimage; ++ dma_cookie_t cookie; ++ int ret = 0; ++ ++ addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); ++ desc = dmaengine_prep_slave_single(csi->dma.chan, addr, len, ++ DMA_DEV_TO_MEM, ++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK); ++ if (!desc) ++ return -EIO; ++ ++ desc->callback = ti_csi2rx_dma_callback; ++ desc->callback_param = buf; ++ ++ cookie = dmaengine_submit(desc); ++ ret = dma_submit_error(cookie); ++ if (ret) ++ return ret; ++ ++ dma_async_issue_pending(csi->dma.chan); ++ ++ return 0; ++} ++ ++static void ti_csi2rx_stop_dma(struct ti_csi2rx_dev *csi) ++{ ++ struct ti_csi2rx_dma *dma = &csi->dma; ++ enum ti_csi2rx_dma_state state; ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&dma->lock, flags); ++ state = csi->dma.state; ++ dma->state = TI_CSI2RX_DMA_STOPPED; ++ spin_unlock_irqrestore(&dma->lock, flags); ++ ++ if (state != TI_CSI2RX_DMA_STOPPED) { ++ /* ++ * Normal DMA termination does not clean up pending data on ++ * the endpoint if multiple streams are running and only one ++ * is stopped, as the module-level pixel reset cannot be ++ * enforced before terminating DMA. ++ */ ++ ret = ti_csi2rx_drain_dma(csi); ++ if (ret && ret != -ETIMEDOUT) ++ dev_warn(csi->dev, ++ "Failed to drain DMA. Next frame might be bogus\n"); ++ } ++ ++ ret = dmaengine_terminate_sync(csi->dma.chan); ++ if (ret) ++ dev_err(csi->dev, "Failed to stop DMA: %d\n", ret); ++} ++ ++static void ti_csi2rx_cleanup_buffers(struct ti_csi2rx_dev *csi, ++ enum vb2_buffer_state state) ++{ ++ struct ti_csi2rx_dma *dma = &csi->dma; ++ struct ti_csi2rx_buffer *buf, *tmp; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dma->lock, flags); ++ list_for_each_entry_safe(buf, tmp, &csi->dma.queue, list) { ++ list_del(&buf->list); ++ vb2_buffer_done(&buf->vb.vb2_buf, state); ++ } ++ list_for_each_entry_safe(buf, tmp, &csi->dma.submitted, list) { ++ list_del(&buf->list); ++ vb2_buffer_done(&buf->vb.vb2_buf, state); ++ } ++ spin_unlock_irqrestore(&dma->lock, flags); ++} ++ ++static int ti_csi2rx_queue_setup(struct vb2_queue *q, unsigned int *nbuffers, ++ unsigned int *nplanes, unsigned int sizes[], ++ struct device *alloc_devs[]) ++{ ++ struct ti_csi2rx_dev *csi = vb2_get_drv_priv(q); ++ unsigned int size = csi->v_fmt.fmt.pix.sizeimage; ++ ++ if (*nplanes) { ++ if (sizes[0] < size) ++ return -EINVAL; ++ size = sizes[0]; ++ } ++ ++ *nplanes = 1; ++ sizes[0] = size; ++ ++ return 0; ++} ++ ++static int ti_csi2rx_buffer_prepare(struct vb2_buffer *vb) ++{ ++ struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vb->vb2_queue); ++ unsigned long size = csi->v_fmt.fmt.pix.sizeimage; ++ ++ if (vb2_plane_size(vb, 0) < size) { ++ dev_err(csi->dev, "Data will not fit into plane\n"); ++ return -EINVAL; ++ } ++ ++ vb2_set_plane_payload(vb, 0, size); ++ return 0; ++} ++ ++static void ti_csi2rx_buffer_queue(struct vb2_buffer *vb) ++{ ++ struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vb->vb2_queue); ++ struct ti_csi2rx_buffer *buf; ++ struct ti_csi2rx_dma *dma = &csi->dma; ++ bool restart_dma = false; ++ unsigned long flags = 0; ++ int ret; ++ ++ buf = container_of(vb, struct ti_csi2rx_buffer, vb.vb2_buf); ++ buf->csi = csi; ++ ++ spin_lock_irqsave(&dma->lock, flags); ++ /* ++ * Usually the DMA callback takes care of queueing the pending buffers. ++ * But if DMA has stalled due to lack of buffers, restart it now. ++ */ ++ if (dma->state == TI_CSI2RX_DMA_IDLE) { ++ /* ++ * Do not restart DMA with the lock held because ++ * ti_csi2rx_drain_dma() might block for completion. ++ * There won't be a race on queueing DMA anyway since the ++ * callback is not being fired. ++ */ ++ restart_dma = true; ++ dma->state = TI_CSI2RX_DMA_ACTIVE; ++ } else { ++ list_add_tail(&buf->list, &dma->queue); ++ } ++ spin_unlock_irqrestore(&dma->lock, flags); ++ ++ if (restart_dma) { ++ /* ++ * Once frames start dropping, some data gets stuck in the DMA ++ * pipeline somewhere. So the first DMA transfer after frame ++ * drops gives a partial frame. This is obviously not useful to ++ * the application and will only confuse it. Issue a DMA ++ * transaction to drain that up. ++ */ ++ ret = ti_csi2rx_drain_dma(csi); ++ if (ret && ret != -ETIMEDOUT) ++ dev_warn(csi->dev, ++ "Failed to drain DMA. Next frame might be bogus\n"); ++ ++ ret = ti_csi2rx_start_dma(csi, buf); ++ if (ret) { ++ dev_err(csi->dev, "Failed to start DMA: %d\n", ret); ++ spin_lock_irqsave(&dma->lock, flags); ++ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); ++ dma->state = TI_CSI2RX_DMA_IDLE; ++ spin_unlock_irqrestore(&dma->lock, flags); ++ } else { ++ spin_lock_irqsave(&dma->lock, flags); ++ list_add_tail(&buf->list, &dma->submitted); ++ spin_unlock_irqrestore(&dma->lock, flags); ++ } ++ } ++} ++ ++static int ti_csi2rx_start_streaming(struct vb2_queue *vq, unsigned int count) ++{ ++ struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vq); ++ struct ti_csi2rx_dma *dma = &csi->dma; ++ struct ti_csi2rx_buffer *buf; ++ unsigned long flags; ++ int ret = 0; ++ ++ spin_lock_irqsave(&dma->lock, flags); ++ if (list_empty(&dma->queue)) ++ ret = -EIO; ++ spin_unlock_irqrestore(&dma->lock, flags); ++ if (ret) ++ return ret; ++ ++ ret = video_device_pipeline_start(&csi->vdev, &csi->pipe); ++ if (ret) ++ goto err; ++ ++ ti_csi2rx_setup_shim(csi); ++ ++ csi->sequence = 0; ++ ++ spin_lock_irqsave(&dma->lock, flags); ++ buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list); ++ ++ ret = ti_csi2rx_start_dma(csi, buf); ++ if (ret) { ++ dev_err(csi->dev, "Failed to start DMA: %d\n", ret); ++ spin_unlock_irqrestore(&dma->lock, flags); ++ goto err_pipeline; ++ } ++ ++ list_move_tail(&buf->list, &dma->submitted); ++ dma->state = TI_CSI2RX_DMA_ACTIVE; ++ spin_unlock_irqrestore(&dma->lock, flags); ++ ++ ret = v4l2_subdev_call(csi->source, video, s_stream, 1); ++ if (ret) ++ goto err_dma; ++ ++ return 0; ++ ++err_dma: ++ ti_csi2rx_stop_dma(csi); ++err_pipeline: ++ video_device_pipeline_stop(&csi->vdev); ++ writel(0, csi->shim + SHIM_CNTL); ++ writel(0, csi->shim + SHIM_DMACNTX); ++err: ++ ti_csi2rx_cleanup_buffers(csi, VB2_BUF_STATE_QUEUED); ++ return ret; ++} ++ ++static void ti_csi2rx_stop_streaming(struct vb2_queue *vq) ++{ ++ struct ti_csi2rx_dev *csi = vb2_get_drv_priv(vq); ++ int ret; ++ ++ video_device_pipeline_stop(&csi->vdev); ++ ++ writel(0, csi->shim + SHIM_CNTL); ++ writel(0, csi->shim + SHIM_DMACNTX); ++ ++ ret = v4l2_subdev_call(csi->source, video, s_stream, 0); ++ if (ret) ++ dev_err(csi->dev, "Failed to stop subdev stream\n"); ++ ++ ti_csi2rx_stop_dma(csi); ++ ti_csi2rx_cleanup_buffers(csi, VB2_BUF_STATE_ERROR); ++} ++ ++static const struct vb2_ops csi_vb2_qops = { ++ .queue_setup = ti_csi2rx_queue_setup, ++ .buf_prepare = ti_csi2rx_buffer_prepare, ++ .buf_queue = ti_csi2rx_buffer_queue, ++ .start_streaming = ti_csi2rx_start_streaming, ++ .stop_streaming = ti_csi2rx_stop_streaming, ++ .wait_prepare = vb2_ops_wait_prepare, ++ .wait_finish = vb2_ops_wait_finish, ++}; ++ ++static int ti_csi2rx_init_vb2q(struct ti_csi2rx_dev *csi) ++{ ++ struct vb2_queue *q = &csi->vidq; ++ int ret; ++ ++ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ q->io_modes = VB2_MMAP | VB2_DMABUF; ++ q->drv_priv = csi; ++ q->buf_struct_size = sizeof(struct ti_csi2rx_buffer); ++ q->ops = &csi_vb2_qops; ++ q->mem_ops = &vb2_dma_contig_memops; ++ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; ++ q->dev = dmaengine_get_dma_device(csi->dma.chan); ++ q->lock = &csi->mutex; ++ q->min_buffers_needed = 1; ++ ++ ret = vb2_queue_init(q); ++ if (ret) ++ return ret; ++ ++ csi->vdev.queue = q; ++ ++ return 0; ++} ++ ++static int ti_csi2rx_link_validate(struct media_link *link) ++{ ++ struct media_entity *entity = link->sink->entity; ++ struct video_device *vdev = media_entity_to_video_device(entity); ++ struct ti_csi2rx_dev *csi = container_of(vdev, struct ti_csi2rx_dev, vdev); ++ struct v4l2_pix_format *csi_fmt = &csi->v_fmt.fmt.pix; ++ struct v4l2_subdev_format source_fmt = { ++ .which = V4L2_SUBDEV_FORMAT_ACTIVE, ++ .pad = link->source->index, ++ }; ++ const struct ti_csi2rx_fmt *ti_fmt; ++ int ret; ++ ++ ret = v4l2_subdev_call_state_active(csi->source, pad, ++ get_fmt, &source_fmt); ++ if (ret) ++ return ret; ++ ++ if (source_fmt.format.width != csi_fmt->width) { ++ dev_dbg(csi->dev, "Width does not match (source %u, sink %u)\n", ++ source_fmt.format.width, csi_fmt->width); ++ return -EPIPE; ++ } ++ ++ if (source_fmt.format.height != csi_fmt->height) { ++ dev_dbg(csi->dev, "Height does not match (source %u, sink %u)\n", ++ source_fmt.format.height, csi_fmt->height); ++ return -EPIPE; ++ } ++ ++ if (source_fmt.format.field != csi_fmt->field && ++ csi_fmt->field != V4L2_FIELD_NONE) { ++ dev_dbg(csi->dev, "Field does not match (source %u, sink %u)\n", ++ source_fmt.format.field, csi_fmt->field); ++ return -EPIPE; ++ } ++ ++ ti_fmt = find_format_by_code(source_fmt.format.code); ++ if (!ti_fmt) { ++ dev_dbg(csi->dev, "Media bus format 0x%x not supported\n", ++ source_fmt.format.code); ++ return -EPIPE; ++ } ++ ++ if (ti_fmt->fourcc != csi_fmt->pixelformat) { ++ dev_dbg(csi->dev, ++ "Cannot transform source fmt 0x%x to sink fmt 0x%x\n", ++ ti_fmt->fourcc, csi_fmt->pixelformat); ++ return -EPIPE; ++ } ++ ++ return 0; ++} ++ ++static const struct media_entity_operations ti_csi2rx_video_entity_ops = { ++ .link_validate = ti_csi2rx_link_validate, ++}; ++ ++static int ti_csi2rx_init_dma(struct ti_csi2rx_dev *csi) ++{ ++ struct dma_slave_config cfg = { ++ .src_addr_width = DMA_SLAVE_BUSWIDTH_16_BYTES, ++ }; ++ int ret; ++ ++ INIT_LIST_HEAD(&csi->dma.queue); ++ INIT_LIST_HEAD(&csi->dma.submitted); ++ spin_lock_init(&csi->dma.lock); ++ ++ csi->dma.state = TI_CSI2RX_DMA_STOPPED; ++ ++ csi->dma.chan = dma_request_chan(csi->dev, "rx0"); ++ if (IS_ERR(csi->dma.chan)) ++ return PTR_ERR(csi->dma.chan); ++ ++ ret = dmaengine_slave_config(csi->dma.chan, &cfg); ++ if (ret) { ++ dma_release_channel(csi->dma.chan); ++ return ret; ++ } ++ ++ csi->dma.drain.len = DRAIN_BUFFER_SIZE; ++ csi->dma.drain.vaddr = dma_alloc_coherent(csi->dev, csi->dma.drain.len, ++ &csi->dma.drain.paddr, ++ GFP_KERNEL); ++ if (!csi->dma.drain.vaddr) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int ti_csi2rx_v4l2_init(struct ti_csi2rx_dev *csi) ++{ ++ struct media_device *mdev = &csi->mdev; ++ struct video_device *vdev = &csi->vdev; ++ const struct ti_csi2rx_fmt *fmt; ++ struct v4l2_pix_format *pix_fmt = &csi->v_fmt.fmt.pix; ++ int ret; ++ ++ fmt = find_format_by_fourcc(V4L2_PIX_FMT_UYVY); ++ if (!fmt) ++ return -EINVAL; ++ ++ pix_fmt->width = 640; ++ pix_fmt->height = 480; ++ pix_fmt->field = V4L2_FIELD_NONE; ++ pix_fmt->colorspace = V4L2_COLORSPACE_SRGB; ++ pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601, ++ pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE, ++ pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB, ++ ++ ti_csi2rx_fill_fmt(fmt, &csi->v_fmt); ++ ++ mdev->dev = csi->dev; ++ mdev->hw_revision = 1; ++ strscpy(mdev->model, "TI-CSI2RX", sizeof(mdev->model)); ++ ++ media_device_init(mdev); ++ ++ strscpy(vdev->name, TI_CSI2RX_MODULE_NAME, sizeof(vdev->name)); ++ vdev->v4l2_dev = &csi->v4l2_dev; ++ vdev->vfl_dir = VFL_DIR_RX; ++ vdev->fops = &csi_fops; ++ vdev->ioctl_ops = &csi_ioctl_ops; ++ vdev->release = video_device_release_empty; ++ vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | ++ V4L2_CAP_IO_MC; ++ vdev->lock = &csi->mutex; ++ video_set_drvdata(vdev, csi); ++ ++ csi->pad.flags = MEDIA_PAD_FL_SINK; ++ vdev->entity.ops = &ti_csi2rx_video_entity_ops; ++ ret = media_entity_pads_init(&csi->vdev.entity, 1, &csi->pad); ++ if (ret) ++ return ret; ++ ++ csi->v4l2_dev.mdev = mdev; ++ ++ ret = v4l2_device_register(csi->dev, &csi->v4l2_dev); ++ if (ret) ++ return ret; ++ ++ ret = media_device_register(mdev); ++ if (ret) { ++ v4l2_device_unregister(&csi->v4l2_dev); ++ media_device_cleanup(mdev); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void ti_csi2rx_cleanup_dma(struct ti_csi2rx_dev *csi) ++{ ++ dma_free_coherent(csi->dev, csi->dma.drain.len, ++ csi->dma.drain.vaddr, csi->dma.drain.paddr); ++ csi->dma.drain.vaddr = NULL; ++ dma_release_channel(csi->dma.chan); ++} ++ ++static void ti_csi2rx_cleanup_v4l2(struct ti_csi2rx_dev *csi) ++{ ++ media_device_unregister(&csi->mdev); ++ v4l2_device_unregister(&csi->v4l2_dev); ++ media_device_cleanup(&csi->mdev); ++} ++ ++static void ti_csi2rx_cleanup_subdev(struct ti_csi2rx_dev *csi) ++{ ++ v4l2_async_nf_unregister(&csi->notifier); ++ v4l2_async_nf_cleanup(&csi->notifier); ++} ++ ++static void ti_csi2rx_cleanup_vb2q(struct ti_csi2rx_dev *csi) ++{ ++ vb2_queue_release(&csi->vidq); ++} ++ ++static int ti_csi2rx_probe(struct platform_device *pdev) ++{ ++ struct ti_csi2rx_dev *csi; ++ int ret; ++ ++ csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL); ++ if (!csi) ++ return -ENOMEM; ++ ++ csi->dev = &pdev->dev; ++ platform_set_drvdata(pdev, csi); ++ ++ mutex_init(&csi->mutex); ++ csi->shim = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(csi->shim)) { ++ ret = PTR_ERR(csi->shim); ++ goto err_mutex; ++ } ++ ++ ret = ti_csi2rx_init_dma(csi); ++ if (ret) ++ goto err_mutex; ++ ++ ret = ti_csi2rx_v4l2_init(csi); ++ if (ret) ++ goto err_dma; ++ ++ ret = ti_csi2rx_init_vb2q(csi); ++ if (ret) ++ goto err_v4l2; ++ ++ ret = ti_csi2rx_notifier_register(csi); ++ if (ret) ++ goto err_vb2q; ++ ++ ret = of_platform_populate(csi->dev->of_node, NULL, NULL, csi->dev); ++ if (ret) { ++ dev_err(csi->dev, "Failed to create children: %d\n", ret); ++ goto err_subdev; ++ } ++ ++ return 0; ++ ++err_subdev: ++ ti_csi2rx_cleanup_subdev(csi); ++err_vb2q: ++ ti_csi2rx_cleanup_vb2q(csi); ++err_v4l2: ++ ti_csi2rx_cleanup_v4l2(csi); ++err_dma: ++ ti_csi2rx_cleanup_dma(csi); ++err_mutex: ++ mutex_destroy(&csi->mutex); ++ return ret; ++} ++ ++static int ti_csi2rx_remove(struct platform_device *pdev) ++{ ++ struct ti_csi2rx_dev *csi = platform_get_drvdata(pdev); ++ ++ video_unregister_device(&csi->vdev); ++ ++ ti_csi2rx_cleanup_vb2q(csi); ++ ti_csi2rx_cleanup_subdev(csi); ++ ti_csi2rx_cleanup_v4l2(csi); ++ ti_csi2rx_cleanup_dma(csi); ++ ++ mutex_destroy(&csi->mutex); ++ ++ return 0; ++} ++ ++static const struct of_device_id ti_csi2rx_of_match[] = { ++ { .compatible = "ti,j721e-csi2rx-shim", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, ti_csi2rx_of_match); ++ ++static struct platform_driver ti_csi2rx_pdrv = { ++ .probe = ti_csi2rx_probe, ++ .remove = ti_csi2rx_remove, ++ .driver = { ++ .name = TI_CSI2RX_MODULE_NAME, ++ .of_match_table = ti_csi2rx_of_match, ++ }, ++}; ++ ++module_platform_driver(ti_csi2rx_pdrv); ++ ++MODULE_DESCRIPTION("TI J721E CSI2 RX Driver"); ++MODULE_AUTHOR("Jai Luthra "); ++MODULE_LICENSE("GPL"); +diff -Naur --no-dereference a/drivers/media/platform/ti/j721e-csi2rx/Makefile b/drivers/media/platform/ti/j721e-csi2rx/Makefile +--- a/drivers/media/platform/ti/j721e-csi2rx/Makefile 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/media/platform/ti/j721e-csi2rx/Makefile 2024-03-28 11:26:09.897017444 -0400 +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_VIDEO_TI_J721E_CSI2RX) += j721e-csi2rx.o +diff -Naur --no-dereference a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig +--- a/drivers/media/platform/ti/Kconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/ti/Kconfig 2024-03-28 11:26:09.897017444 -0400 +@@ -63,6 +63,18 @@ + help + Enable debug messages on VPE driver. + ++config VIDEO_TI_J721E_CSI2RX ++ tristate "TI J721E CSI2RX wrapper layer driver" ++ depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API ++ depends on MEDIA_SUPPORT && MEDIA_CONTROLLER ++ depends on (PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX) || COMPILE_TEST ++ depends on ARCH_K3 || COMPILE_TEST ++ select VIDEOBUF2_DMA_CONTIG ++ select V4L2_FWNODE ++ help ++ Support for TI CSI2RX wrapper layer. This just enables the wrapper driver. ++ The Cadence CSI2RX bridge driver needs to be enabled separately. ++ + source "drivers/media/platform/ti/am437x/Kconfig" + source "drivers/media/platform/ti/davinci/Kconfig" + source "drivers/media/platform/ti/omap/Kconfig" +diff -Naur --no-dereference a/drivers/media/platform/ti/Makefile b/drivers/media/platform/ti/Makefile +--- a/drivers/media/platform/ti/Makefile 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/platform/ti/Makefile 2024-03-28 11:26:09.897017444 -0400 +@@ -3,5 +3,6 @@ + obj-y += cal/ + obj-y += vpe/ + obj-y += davinci/ ++obj-y += j721e-csi2rx/ + obj-y += omap/ + obj-y += omap3isp/ +diff -Naur --no-dereference a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c +--- a/drivers/media/v4l2-core/v4l2-mem2mem.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c 2024-03-28 11:26:09.897017444 -0400 +@@ -301,9 +301,12 @@ + + dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx); + +- if (!m2m_ctx->out_q_ctx.q.streaming +- || !m2m_ctx->cap_q_ctx.q.streaming) { +- dprintk("Streaming needs to be on for both queues\n"); ++ if (!m2m_ctx->out_q_ctx.q.streaming || ++ (!m2m_ctx->cap_q_ctx.q.streaming && !m2m_ctx->ignore_cap_streaming)) { ++ if (!m2m_ctx->ignore_cap_streaming) ++ dprintk("Streaming needs to be on for both queues\n"); ++ else ++ dprintk("Streaming needs to be on for the OUTPUT queue\n"); + return; + } + +diff -Naur --no-dereference a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c +--- a/drivers/misc/pci_endpoint_test.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/misc/pci_endpoint_test.c 2024-03-28 11:26:09.897017444 -0400 +@@ -263,6 +263,15 @@ + return false; + } + ++static const u32 bar_test_pattern[] = { ++ 0xA0A0A0A0, ++ 0xA1A1A1A1, ++ 0xA2A2A2A2, ++ 0xA3A3A3A3, ++ 0xA4A4A4A4, ++ 0xA5A5A5A5, ++}; ++ + static bool pci_endpoint_test_bar(struct pci_endpoint_test *test, + enum pci_barno barno) + { +@@ -280,11 +289,12 @@ + size = 0x4; + + for (j = 0; j < size; j += 4) +- pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0); ++ pci_endpoint_test_bar_writel(test, barno, j, ++ bar_test_pattern[barno]); + + for (j = 0; j < size; j += 4) { + val = pci_endpoint_test_bar_readl(test, barno, j); +- if (val != 0xA0A0A0A0) ++ if (val != bar_test_pattern[barno]) + return false; + } + +diff -Naur --no-dereference a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c +--- a/drivers/mmc/host/sdhci_am654.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/mmc/host/sdhci_am654.c 2024-03-28 11:26:09.897017444 -0400 +@@ -141,7 +141,6 @@ + + struct sdhci_am654_data { + struct regmap *base; +- bool legacy_otapdly; + int otap_del_sel[ARRAY_SIZE(td)]; + int itap_del_sel[ARRAY_SIZE(td)]; + int clkbuf_sel; +@@ -272,11 +271,7 @@ + sdhci_set_clock(host, clock); + + /* Setup DLL Output TAP delay */ +- if (sdhci_am654->legacy_otapdly) +- otap_del_sel = sdhci_am654->otap_del_sel[0]; +- else +- otap_del_sel = sdhci_am654->otap_del_sel[timing]; +- ++ otap_del_sel = sdhci_am654->otap_del_sel[timing]; + otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0; + + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; +@@ -314,10 +309,7 @@ + u32 mask, val; + + /* Setup DLL Output TAP delay */ +- if (sdhci_am654->legacy_otapdly) +- otap_del_sel = sdhci_am654->otap_del_sel[0]; +- else +- otap_del_sel = sdhci_am654->otap_del_sel[timing]; ++ otap_del_sel = sdhci_am654->otap_del_sel[timing]; + + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; + val = (0x1 << OTAPDLYENA_SHIFT) | +@@ -577,32 +569,15 @@ + int i; + int ret; + +- ret = device_property_read_u32(dev, td[MMC_TIMING_LEGACY].otap_binding, +- &sdhci_am654->otap_del_sel[MMC_TIMING_LEGACY]); +- if (ret) { +- /* +- * ti,otap-del-sel-legacy is mandatory, look for old binding +- * if not found. +- */ +- ret = device_property_read_u32(dev, "ti,otap-del-sel", +- &sdhci_am654->otap_del_sel[0]); +- if (ret) { +- dev_err(dev, "Couldn't find otap-del-sel\n"); +- +- return ret; +- } +- +- dev_info(dev, "Using legacy binding ti,otap-del-sel\n"); +- sdhci_am654->legacy_otapdly = true; +- +- return 0; +- } +- + for (i = MMC_TIMING_LEGACY; i <= MMC_TIMING_MMC_HS400; i++) { + + ret = device_property_read_u32(dev, td[i].otap_binding, + &sdhci_am654->otap_del_sel[i]); + if (ret) { ++ if (i == MMC_TIMING_LEGACY) { ++ dev_err(dev, "Couldn't find mandatory ti,otap-del-sel-legacy\n"); ++ return ret; ++ } + dev_dbg(dev, "Couldn't find %s\n", + td[i].otap_binding); + /* +diff -Naur --no-dereference a/drivers/mux/mmio.c b/drivers/mux/mmio.c +--- a/drivers/mux/mmio.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/mux/mmio.c 2024-03-28 11:26:09.897017444 -0400 +@@ -44,15 +44,20 @@ + int ret; + int i; + +- if (of_device_is_compatible(np, "mmio-mux")) ++ if (of_device_is_compatible(np, "mmio-mux")) { + regmap = syscon_node_to_regmap(np->parent); +- else +- regmap = dev_get_regmap(dev->parent, NULL) ?: ERR_PTR(-ENODEV); +- if (IS_ERR(regmap)) { +- ret = PTR_ERR(regmap); +- dev_err(dev, "failed to get regmap: %d\n", ret); +- return ret; ++ } else { ++ regmap = device_node_to_regmap(np); ++ /* Fallback to checking the parent node on "real" errors. */ ++ if (IS_ERR(regmap) && regmap != ERR_PTR(-EPROBE_DEFER)) { ++ regmap = dev_get_regmap(dev->parent, NULL); ++ if (!regmap) ++ regmap = ERR_PTR(-ENODEV); ++ } + } ++ if (IS_ERR(regmap)) ++ return dev_err_probe(dev, PTR_ERR(regmap), ++ "failed to get regmap\n"); + + ret = of_property_count_u32_elems(np, "mux-reg-masks"); + if (ret == 0 || ret % 2) +diff -Naur --no-dereference a/drivers/net/ethernet/altera/altera_tse.h b/drivers/net/ethernet/altera/altera_tse.h +--- a/drivers/net/ethernet/altera/altera_tse.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/altera/altera_tse.h 2024-03-28 11:26:09.897017444 -0400 +@@ -472,7 +472,7 @@ + /* ethtool msglvl option */ + u32 msg_enable; + +- struct altera_dmaops *dmaops; ++ const struct altera_dmaops *dmaops; + + struct phylink *phylink; + struct phylink_config phylink_config; +diff -Naur --no-dereference a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c +--- a/drivers/net/ethernet/altera/altera_tse_main.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/altera/altera_tse_main.c 2024-03-28 11:26:09.897017444 -0400 +@@ -29,13 +29,13 @@ + #include + #include + #include +-#include ++#include + #include + #include +-#include + #include + #include + #include ++#include + #include + #include + #include +@@ -82,8 +82,6 @@ + + #define TXQUEUESTOP_THRESHHOLD 2 + +-static const struct of_device_id altera_tse_ids[]; +- + static inline u32 tse_tx_avail(struct altera_tse_private *priv) + { + return priv->tx_cons + priv->tx_ring_size - priv->tx_prod - 1; +@@ -1133,7 +1131,6 @@ + */ + static int altera_tse_probe(struct platform_device *pdev) + { +- const struct of_device_id *of_id = NULL; + struct regmap_config pcs_regmap_cfg; + struct altera_tse_private *priv; + struct mdio_regmap_config mrc; +@@ -1159,11 +1156,7 @@ + priv->dev = ndev; + priv->msg_enable = netif_msg_init(debug, default_msg_level); + +- of_id = of_match_device(altera_tse_ids, &pdev->dev); +- +- if (of_id) +- priv->dmaops = (struct altera_dmaops *)of_id->data; +- ++ priv->dmaops = device_get_match_data(&pdev->dev); + + if (priv->dmaops && + priv->dmaops->altera_dtype == ALTERA_DTYPE_SGDMA) { +diff -Naur --no-dereference a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c +--- a/drivers/net/ethernet/amd/xgbe/xgbe-platform.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-platform.c 2024-03-28 11:26:09.897017444 -0400 +@@ -123,9 +123,7 @@ + #include + #include + #include +-#include + #include +-#include + #include + #include + #include +@@ -135,17 +133,6 @@ + #include "xgbe-common.h" + + #ifdef CONFIG_ACPI +-static const struct acpi_device_id xgbe_acpi_match[]; +- +-static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata) +-{ +- const struct acpi_device_id *id; +- +- id = acpi_match_device(xgbe_acpi_match, pdata->dev); +- +- return id ? (struct xgbe_version_data *)id->driver_data : NULL; +-} +- + static int xgbe_acpi_support(struct xgbe_prv_data *pdata) + { + struct device *dev = pdata->dev; +@@ -173,11 +160,6 @@ + return 0; + } + #else /* CONFIG_ACPI */ +-static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata) +-{ +- return NULL; +-} +- + static int xgbe_acpi_support(struct xgbe_prv_data *pdata) + { + return -EINVAL; +@@ -185,17 +167,6 @@ + #endif /* CONFIG_ACPI */ + + #ifdef CONFIG_OF +-static const struct of_device_id xgbe_of_match[]; +- +-static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata) +-{ +- const struct of_device_id *id; +- +- id = of_match_device(xgbe_of_match, pdata->dev); +- +- return id ? (struct xgbe_version_data *)id->data : NULL; +-} +- + static int xgbe_of_support(struct xgbe_prv_data *pdata) + { + struct device *dev = pdata->dev; +@@ -244,11 +215,6 @@ + return phy_pdev; + } + #else /* CONFIG_OF */ +-static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata) +-{ +- return NULL; +-} +- + static int xgbe_of_support(struct xgbe_prv_data *pdata) + { + return -EINVAL; +@@ -290,12 +256,6 @@ + return phy_pdev; + } + +-static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata) +-{ +- return pdata->use_acpi ? xgbe_acpi_vdata(pdata) +- : xgbe_of_vdata(pdata); +-} +- + static int xgbe_platform_probe(struct platform_device *pdev) + { + struct xgbe_prv_data *pdata; +@@ -321,7 +281,7 @@ + pdata->use_acpi = dev->of_node ? 0 : 1; + + /* Get the version data */ +- pdata->vdata = xgbe_get_vdata(pdata); ++ pdata->vdata = (struct xgbe_version_data *)device_get_match_data(dev); + + phy_pdev = xgbe_get_phy_pdev(pdata); + if (!phy_pdev) { +diff -Naur --no-dereference a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c 2024-03-28 11:26:09.897017444 -0400 +@@ -2018,7 +2018,6 @@ + struct xgene_enet_pdata *pdata; + struct device *dev = &pdev->dev; + void (*link_state)(struct work_struct *); +- const struct of_device_id *of_id; + int ret; + + ndev = alloc_etherdev_mqs(sizeof(struct xgene_enet_pdata), +@@ -2039,19 +2038,7 @@ + NETIF_F_GRO | + NETIF_F_SG; + +- of_id = of_match_device(xgene_enet_of_match, &pdev->dev); +- if (of_id) { +- pdata->enet_id = (uintptr_t)of_id->data; +- } +-#ifdef CONFIG_ACPI +- else { +- const struct acpi_device_id *acpi_id; +- +- acpi_id = acpi_match_device(xgene_enet_acpi_match, &pdev->dev); +- if (acpi_id) +- pdata->enet_id = (enum xgene_enet_id) acpi_id->driver_data; +- } +-#endif ++ pdata->enet_id = (enum xgene_enet_id)device_get_match_data(&pdev->dev); + if (!pdata->enet_id) { + ret = -ENODEV; + goto err; +diff -Naur --no-dereference a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h 2024-03-28 11:26:09.897017444 -0400 +@@ -15,9 +15,10 @@ + #include + #include + #include +-#include ++#include + #include + #include ++#include + #include + #include + #include +diff -Naur --no-dereference a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +--- a/drivers/net/ethernet/freescale/fec_main.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/freescale/fec_main.c 2024-03-28 11:26:09.897017444 -0400 +@@ -52,11 +52,11 @@ + #include + #include + #include ++#include + #include + #include + #include + #include +-#include + #include + #include + #include +@@ -4289,14 +4289,13 @@ + phy_interface_t interface; + struct net_device *ndev; + int i, irq, ret = 0; +- const struct of_device_id *of_id; + static int dev_id; + struct device_node *np = pdev->dev.of_node, *phy_node; + int num_tx_qs; + int num_rx_qs; + char irq_name[8]; + int irq_cnt; +- struct fec_devinfo *dev_info; ++ const struct fec_devinfo *dev_info; + + fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); + +@@ -4311,10 +4310,9 @@ + /* setup board info structure */ + fep = netdev_priv(ndev); + +- of_id = of_match_device(fec_dt_ids, &pdev->dev); +- if (of_id) +- pdev->id_entry = of_id->data; +- dev_info = (struct fec_devinfo *)pdev->id_entry->driver_data; ++ dev_info = device_get_match_data(&pdev->dev); ++ if (!dev_info) ++ dev_info = (const struct fec_devinfo *)pdev->id_entry->driver_data; + if (dev_info) + fep->quirks = dev_info->quirks; + +diff -Naur --no-dereference a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c 2024-03-28 11:26:09.897017444 -0400 +@@ -35,10 +35,9 @@ + #include + #include + #include ++#include + #include + #include +-#include +-#include + #include + #include + +@@ -884,9 +883,9 @@ + /**************************************************************************************/ + + #ifdef CONFIG_FS_ENET_HAS_FEC +-#define IS_FEC(match) ((match)->data == &fs_fec_ops) ++#define IS_FEC(ops) ((ops) == &fs_fec_ops) + #else +-#define IS_FEC(match) 0 ++#define IS_FEC(ops) 0 + #endif + + static const struct net_device_ops fs_enet_netdev_ops = { +@@ -903,10 +902,9 @@ + #endif + }; + +-static const struct of_device_id fs_enet_match[]; + static int fs_enet_probe(struct platform_device *ofdev) + { +- const struct of_device_id *match; ++ const struct fs_ops *ops; + struct net_device *ndev; + struct fs_enet_private *fep; + struct fs_platform_info *fpi; +@@ -916,15 +914,15 @@ + const char *phy_connection_type; + int privsize, len, ret = -ENODEV; + +- match = of_match_device(fs_enet_match, &ofdev->dev); +- if (!match) ++ ops = device_get_match_data(&ofdev->dev); ++ if (!ops) + return -EINVAL; + + fpi = kzalloc(sizeof(*fpi), GFP_KERNEL); + if (!fpi) + return -ENOMEM; + +- if (!IS_FEC(match)) { ++ if (!IS_FEC(ops)) { + data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len); + if (!data || len != 4) + goto out_free_fpi; +@@ -986,7 +984,7 @@ + fep->dev = &ofdev->dev; + fep->ndev = ndev; + fep->fpi = fpi; +- fep->ops = match->data; ++ fep->ops = ops; + + ret = fep->ops->setup_data(ndev); + if (ret) +diff -Naur --no-dereference a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +--- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c 2024-03-28 11:26:09.897017444 -0400 +@@ -30,9 +30,10 @@ + #include + #include + #include ++#include ++#include + #include + #include +-#include + #include + + #include +@@ -96,20 +97,15 @@ + + } + +-static const struct of_device_id fs_enet_mdio_fec_match[]; + static int fs_enet_mdio_probe(struct platform_device *ofdev) + { +- const struct of_device_id *match; + struct resource res; + struct mii_bus *new_bus; + struct fec_info *fec; + int (*get_bus_freq)(struct device *); + int ret = -ENOMEM, clock, speed; + +- match = of_match_device(fs_enet_mdio_fec_match, &ofdev->dev); +- if (!match) +- return -EINVAL; +- get_bus_freq = match->data; ++ get_bus_freq = device_get_match_data(&ofdev->dev); + + new_bus = mdiobus_alloc(); + if (!new_bus) +diff -Naur --no-dereference a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c +--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c 2024-03-28 11:26:09.901017460 -0400 +@@ -19,9 +19,10 @@ + #include + #include + #include ++#include + #include + #include +-#include ++#include + + #include + #if IS_ENABLED(CONFIG_UCC_GETH) +@@ -407,8 +408,6 @@ + + static int fsl_pq_mdio_probe(struct platform_device *pdev) + { +- const struct of_device_id *id = +- of_match_device(fsl_pq_mdio_match, &pdev->dev); + const struct fsl_pq_mdio_data *data; + struct device_node *np = pdev->dev.of_node; + struct resource res; +@@ -417,15 +416,12 @@ + struct mii_bus *new_bus; + int err; + +- if (!id) { ++ data = device_get_match_data(&pdev->dev); ++ if (!data) { + dev_err(&pdev->dev, "Failed to match device\n"); + return -ENODEV; + } + +- data = id->data; +- +- dev_dbg(&pdev->dev, "found %s compatible node\n", id->compatible); +- + new_bus = mdiobus_alloc_size(sizeof(*priv)); + if (!new_bus) + return -ENOMEM; +diff -Naur --no-dereference a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +--- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c 2024-03-28 11:26:09.901017460 -0400 +@@ -7,7 +7,8 @@ + #include + #include + #include +-#include ++#include ++#include + #include + #include + #include +@@ -1094,7 +1095,6 @@ + { + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; +- const struct of_device_id *of_id = NULL; + struct net_device *ndev; + struct hix5hd2_priv *priv; + struct mii_bus *bus; +@@ -1110,12 +1110,7 @@ + priv->dev = dev; + priv->netdev = ndev; + +- of_id = of_match_device(hix5hd2_of_match, dev); +- if (!of_id) { +- ret = -EINVAL; +- goto out_free_netdev; +- } +- priv->hw_cap = (unsigned long)of_id->data; ++ priv->hw_cap = (unsigned long)device_get_match_data(dev); + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) { +diff -Naur --no-dereference a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c 2024-03-28 11:26:09.901017460 -0400 +@@ -7,8 +7,8 @@ + #include + #include + #include +-#include + #include ++#include + #include + + #include "dwmac4.h" +@@ -76,7 +76,6 @@ + { + struct plat_stmmacenet_data *plat_dat; + struct stmmac_resources stmmac_res; +- const struct of_device_id *match; + struct intel_dwmac *dwmac; + unsigned long rate; + int ret; +@@ -100,10 +99,8 @@ + dwmac->dev = &pdev->dev; + dwmac->tx_clk = NULL; + +- match = of_match_device(intel_eth_plat_match, &pdev->dev); +- if (match && match->data) { +- dwmac->data = (const struct intel_dwmac_data *)match->data; +- ++ dwmac->data = device_get_match_data(&pdev->dev); ++ if (dwmac->data) { + if (dwmac->data->fix_mac_speed) + plat_dat->fix_mac_speed = dwmac->data->fix_mac_speed; + +diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c +--- a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c 2024-03-28 11:26:09.901017460 -0400 +@@ -11,6 +11,7 @@ + #include + + #include "am65-cpsw-nuss.h" ++#include "am65-cpsw-qos.h" + #include "cpsw_ale.h" + #include "am65-cpts.h" + +@@ -662,6 +663,34 @@ + hw_stats[i].offset); + } + ++static void am65_cpsw_get_eth_mac_stats(struct net_device *ndev, ++ struct ethtool_eth_mac_stats *s) ++{ ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ struct am65_cpsw_stats_regs __iomem *stats; ++ ++ stats = port->stat_base; ++ ++ if (s->src != ETHTOOL_MAC_STATS_SRC_AGGREGATE) ++ return; ++ ++ s->FramesTransmittedOK = readl_relaxed(&stats->tx_good_frames); ++ s->SingleCollisionFrames = readl_relaxed(&stats->tx_single_coll_frames); ++ s->MultipleCollisionFrames = readl_relaxed(&stats->tx_mult_coll_frames); ++ s->FramesReceivedOK = readl_relaxed(&stats->rx_good_frames); ++ s->FrameCheckSequenceErrors = readl_relaxed(&stats->rx_crc_errors); ++ s->AlignmentErrors = readl_relaxed(&stats->rx_align_code_errors); ++ s->OctetsTransmittedOK = readl_relaxed(&stats->tx_octets); ++ s->FramesWithDeferredXmissions = readl_relaxed(&stats->tx_deferred_frames); ++ s->LateCollisions = readl_relaxed(&stats->tx_late_collisions); ++ s->CarrierSenseErrors = readl_relaxed(&stats->tx_carrier_sense_errors); ++ s->OctetsReceivedOK = readl_relaxed(&stats->rx_octets); ++ s->MulticastFramesXmittedOK = readl_relaxed(&stats->tx_multicast_frames); ++ s->BroadcastFramesXmittedOK = readl_relaxed(&stats->tx_broadcast_frames); ++ s->MulticastFramesReceivedOK = readl_relaxed(&stats->rx_multicast_frames); ++ s->BroadcastFramesReceivedOK = readl_relaxed(&stats->rx_broadcast_frames); ++}; ++ + static int am65_cpsw_get_ethtool_ts_info(struct net_device *ndev, + struct ethtool_ts_info *info) + { +@@ -715,6 +744,240 @@ + return 0; + } + ++static void am65_cpsw_port_iet_rx_enable(struct am65_cpsw_port *port, bool enable) ++{ ++ u32 val; ++ ++ val = readl(port->port_base + AM65_CPSW_PN_REG_CTL); ++ if (enable) ++ val |= AM65_CPSW_PN_CTL_IET_PORT_EN; ++ else ++ val &= ~AM65_CPSW_PN_CTL_IET_PORT_EN; ++ ++ writel(val, port->port_base + AM65_CPSW_PN_REG_CTL); ++ am65_cpsw_iet_common_enable(port->common); ++} ++ ++static void am65_cpsw_port_iet_tx_enable(struct am65_cpsw_port *port, bool enable) ++{ ++ u32 val; ++ ++ val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ if (enable) ++ val |= AM65_CPSW_PN_IET_MAC_PENABLE; ++ else ++ val &= ~AM65_CPSW_PN_IET_MAC_PENABLE; ++ ++ writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++} ++ ++static int am65_cpsw_get_mm(struct net_device *ndev, struct ethtool_mm_state *state) ++{ ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev); ++ u32 port_ctrl, iet_ctrl, iet_status; ++ u32 add_frag_size; ++ ++ if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS)) ++ return -EOPNOTSUPP; ++ ++ mutex_lock(&priv->mm_lock); ++ ++ iet_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ port_ctrl = readl(port->port_base + AM65_CPSW_PN_REG_CTL); ++ ++ state->tx_enabled = !!(iet_ctrl & AM65_CPSW_PN_IET_MAC_PENABLE); ++ state->pmac_enabled = !!(port_ctrl & AM65_CPSW_PN_CTL_IET_PORT_EN); ++ ++ iet_status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS); ++ ++ if (iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY) ++ state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED; ++ else if (iet_status & AM65_CPSW_PN_MAC_VERIFIED) ++ state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED; ++ else if (iet_status & AM65_CPSW_PN_MAC_VERIFY_FAIL) ++ state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED; ++ else ++ state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN; ++ ++ add_frag_size = AM65_CPSW_PN_IET_MAC_GET_ADDFRAGSIZE(iet_ctrl); ++ state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(add_frag_size); ++ ++ /* Errata i2208: RX min fragment size cannot be less than 124 */ ++ state->rx_min_frag_size = 124; ++ ++ /* FPE active if common tx_enabled and verification success or disabled (forced) */ ++ state->tx_active = state->tx_enabled && ++ (state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED || ++ state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED); ++ state->verify_enabled = !(iet_ctrl & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY); ++ ++ state->verify_time = port->qos.iet.verify_time_ms; ++ ++ /* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime ++ * variable has a range between 1 and 128 ms inclusive. Limit to that. ++ */ ++ state->max_verify_time = 128; ++ ++ mutex_unlock(&priv->mm_lock); ++ ++ return 0; ++} ++ ++static int am65_cpsw_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg, ++ struct netlink_ext_ack *extack) ++{ ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ struct am65_cpsw_ndev_priv *priv = netdev_priv(ndev); ++ struct am65_cpsw_iet *iet = &port->qos.iet; ++ u32 val, add_frag_size; ++ int err; ++ ++ if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS)) ++ return -EOPNOTSUPP; ++ ++ err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size, &add_frag_size, extack); ++ if (err) ++ return err; ++ ++ mutex_lock(&priv->mm_lock); ++ ++ if (cfg->pmac_enabled) { ++ /* change TX & RX FIFO MAX_BLKS as per TRM recommendation */ ++ if (!iet->original_max_blks) ++ iet->original_max_blks = readl(port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); ++ ++ writel(AM65_CPSW_PN_TX_RX_MAX_BLKS_IET, ++ port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); ++ } else if (iet->original_max_blks) { ++ /* restore RX & TX FIFO MAX_BLKS */ ++ writel(iet->original_max_blks, ++ port->port_base + AM65_CPSW_PN_REG_MAX_BLKS); ++ } ++ ++ am65_cpsw_port_iet_rx_enable(port, cfg->pmac_enabled); ++ am65_cpsw_port_iet_tx_enable(port, cfg->tx_enabled); ++ ++ val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ if (cfg->verify_enabled) { ++ val &= ~AM65_CPSW_PN_IET_MAC_DISABLEVERIFY; ++ /* Reset Verify state machine. Verification won't start here. ++ * Verification will be done once link-up. ++ */ ++ val |= AM65_CPSW_PN_IET_MAC_LINKFAIL; ++ } else { ++ val |= AM65_CPSW_PN_IET_MAC_DISABLEVERIFY; ++ /* Clear LINKFAIL to allow verify/response packets */ ++ val &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; ++ } ++ ++ val &= ~AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK; ++ val |= AM65_CPSW_PN_IET_MAC_SET_ADDFRAGSIZE(add_frag_size); ++ writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ++ /* verify_timeout_count can only be set at valid link */ ++ port->qos.iet.verify_time_ms = cfg->verify_time; ++ ++ /* enable/disable preemption based on link status */ ++ am65_cpsw_iet_commit_preemptible_tcs(port); ++ ++ mutex_unlock(&priv->mm_lock); ++ ++ return 0; ++} ++ ++static void am65_cpsw_get_mm_stats(struct net_device *ndev, ++ struct ethtool_mm_stats *s) ++{ ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ void __iomem *base = port->stat_base; ++ ++ s->MACMergeFrameAssOkCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_OK); ++ s->MACMergeFrameAssErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_ASSEMBLY_ERROR); ++ s->MACMergeFrameSmdErrorCount = readl(base + AM65_CPSW_STATN_IET_RX_SMD_ERROR); ++ /* CPSW Functional Spec states: ++ * "The IET stat aMACMergeFragCountRx is derived by adding the ++ * Receive Assembly Error count to this value. i.e. AM65_CPSW_STATN_IET_RX_FRAG" ++ */ ++ s->MACMergeFragCountRx = readl(base + AM65_CPSW_STATN_IET_RX_FRAG) + s->MACMergeFrameAssErrorCount; ++ s->MACMergeFragCountTx = readl(base + AM65_CPSW_STATN_IET_TX_FRAG); ++ s->MACMergeHoldCount = readl(base + AM65_CPSW_STATN_IET_TX_HOLD); ++} ++ ++static int am65_cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, ++ struct kernel_ethtool_coalesce *kernel_coal, ++ struct netlink_ext_ack *extack) ++{ ++ struct am65_cpsw_common *common = am65_ndev_to_common(ndev); ++ struct am65_cpsw_tx_chn *tx_chn; ++ ++ tx_chn = &common->tx_chns[0]; ++ ++ coal->rx_coalesce_usecs = common->rx_pace_timeout / 1000; ++ coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000; ++ ++ return 0; ++} ++ ++static int am65_cpsw_get_per_queue_coalesce(struct net_device *ndev, u32 queue, ++ struct ethtool_coalesce *coal) ++{ ++ struct am65_cpsw_common *common = am65_ndev_to_common(ndev); ++ struct am65_cpsw_tx_chn *tx_chn; ++ ++ if (queue >= AM65_CPSW_MAX_TX_QUEUES) ++ return -EINVAL; ++ ++ tx_chn = &common->tx_chns[queue]; ++ ++ coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000; ++ ++ return 0; ++} ++ ++static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal, ++ struct kernel_ethtool_coalesce *kernel_coal, ++ struct netlink_ext_ack *extack) ++{ ++ struct am65_cpsw_common *common = am65_ndev_to_common(ndev); ++ struct am65_cpsw_tx_chn *tx_chn; ++ ++ tx_chn = &common->tx_chns[0]; ++ ++ if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20) ++ return -EINVAL; ++ ++ if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) ++ return -EINVAL; ++ ++ common->rx_pace_timeout = coal->rx_coalesce_usecs * 1000; ++ tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000; ++ ++ return 0; ++} ++ ++static int am65_cpsw_set_per_queue_coalesce(struct net_device *ndev, u32 queue, ++ struct ethtool_coalesce *coal) ++{ ++ struct am65_cpsw_common *common = am65_ndev_to_common(ndev); ++ struct am65_cpsw_tx_chn *tx_chn; ++ ++ if (queue >= AM65_CPSW_MAX_TX_QUEUES) ++ return -EINVAL; ++ ++ tx_chn = &common->tx_chns[queue]; ++ ++ if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) { ++ dev_info(common->dev, "defaulting to min value of 20us for tx-usecs for tx-%u\n", ++ queue); ++ coal->tx_coalesce_usecs = 20; ++ } ++ ++ tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000; ++ ++ return 0; ++} ++ + const struct ethtool_ops am65_cpsw_ethtool_ops_slave = { + .begin = am65_cpsw_ethtool_op_begin, + .complete = am65_cpsw_ethtool_op_complete, +@@ -729,9 +992,15 @@ + .get_sset_count = am65_cpsw_get_sset_count, + .get_strings = am65_cpsw_get_strings, + .get_ethtool_stats = am65_cpsw_get_ethtool_stats, ++ .get_eth_mac_stats = am65_cpsw_get_eth_mac_stats, + .get_ts_info = am65_cpsw_get_ethtool_ts_info, + .get_priv_flags = am65_cpsw_get_ethtool_priv_flags, + .set_priv_flags = am65_cpsw_set_ethtool_priv_flags, ++ .supported_coalesce_params = ETHTOOL_COALESCE_USECS, ++ .get_coalesce = am65_cpsw_get_coalesce, ++ .set_coalesce = am65_cpsw_set_coalesce, ++ .get_per_queue_coalesce = am65_cpsw_get_per_queue_coalesce, ++ .set_per_queue_coalesce = am65_cpsw_set_per_queue_coalesce, + + .get_link = ethtool_op_get_link, + .get_link_ksettings = am65_cpsw_get_link_ksettings, +@@ -743,4 +1012,7 @@ + .get_eee = am65_cpsw_get_eee, + .set_eee = am65_cpsw_set_eee, + .nway_reset = am65_cpsw_nway_reset, ++ .get_mm = am65_cpsw_get_mm, ++ .set_mm = am65_cpsw_set_mm, ++ .get_mm_stats = am65_cpsw_get_mm_stats, + }; +diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c 2024-03-28 11:26:09.901017460 -0400 +@@ -136,6 +136,8 @@ + NETIF_MSG_IFUP | NETIF_MSG_PROBE | NETIF_MSG_IFDOWN | \ + NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) + ++#define AM65_CPSW_DEFAULT_TX_CHNS 8 ++ + static void am65_cpsw_port_set_sl_mac(struct am65_cpsw_port *slave, + const u8 *dev_addr) + { +@@ -367,10 +369,81 @@ + static void am65_cpsw_init_port_switch_ale(struct am65_cpsw_port *port); + static void am65_cpsw_init_port_emac_ale(struct am65_cpsw_port *port); + ++static void am65_cpsw_nuss_rx_cleanup(void *data, dma_addr_t desc_dma) ++{ ++ struct am65_cpsw_rx_chn *rx_chn = data; ++ struct cppi5_host_desc_t *desc_rx; ++ struct sk_buff *skb; ++ dma_addr_t buf_dma; ++ u32 buf_dma_len; ++ void **swdata; ++ ++ desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma); ++ swdata = cppi5_hdesc_get_swdata(desc_rx); ++ skb = *swdata; ++ cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); ++ k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma); ++ ++ dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE); ++ k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); ++ ++ dev_kfree_skb_any(skb); ++} ++ ++static void am65_cpsw_nuss_xmit_free(struct am65_cpsw_tx_chn *tx_chn, ++ struct cppi5_host_desc_t *desc) ++{ ++ struct cppi5_host_desc_t *first_desc, *next_desc; ++ dma_addr_t buf_dma, next_desc_dma; ++ u32 buf_dma_len; ++ ++ first_desc = desc; ++ next_desc = first_desc; ++ ++ cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len); ++ k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma); ++ ++ dma_unmap_single(tx_chn->dma_dev, buf_dma, buf_dma_len, DMA_TO_DEVICE); ++ ++ next_desc_dma = cppi5_hdesc_get_next_hbdesc(first_desc); ++ k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &next_desc_dma); ++ while (next_desc_dma) { ++ next_desc = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, ++ next_desc_dma); ++ cppi5_hdesc_get_obuf(next_desc, &buf_dma, &buf_dma_len); ++ k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma); ++ ++ dma_unmap_page(tx_chn->dma_dev, buf_dma, buf_dma_len, ++ DMA_TO_DEVICE); ++ ++ next_desc_dma = cppi5_hdesc_get_next_hbdesc(next_desc); ++ k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &next_desc_dma); ++ ++ k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc); ++ } ++ ++ k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc); ++} ++ ++static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma) ++{ ++ struct am65_cpsw_tx_chn *tx_chn = data; ++ struct cppi5_host_desc_t *desc_tx; ++ struct sk_buff *skb; ++ void **swdata; ++ ++ desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma); ++ swdata = cppi5_hdesc_get_swdata(desc_tx); ++ skb = *(swdata); ++ am65_cpsw_nuss_xmit_free(tx_chn, desc_tx); ++ ++ dev_kfree_skb_any(skb); ++} ++ + static int am65_cpsw_nuss_common_open(struct am65_cpsw_common *common) + { + struct am65_cpsw_host *host_p = am65_common_get_host(common); +- int port_idx, i, ret; ++ int port_idx, i, ret, tx; + struct sk_buff *skb; + u32 val, port_mask; + +@@ -437,8 +510,12 @@ + AM65_CPSW_MAX_PACKET_SIZE, + GFP_KERNEL); + if (!skb) { ++ ret = -ENOMEM; + dev_err(common->dev, "cannot allocate skb\n"); +- return -ENOMEM; ++ if (i) ++ goto fail_rx; ++ ++ return ret; + } + + ret = am65_cpsw_nuss_rx_push(common, skb); +@@ -447,17 +524,28 @@ + "cannot submit skb to channel rx, error %d\n", + ret); + kfree_skb(skb); ++ if (i) ++ goto fail_rx; ++ + return ret; + } +- kmemleak_not_leak(skb); + } +- k3_udma_glue_enable_rx_chn(common->rx_chns.rx_chn); + +- for (i = 0; i < common->tx_ch_num; i++) { +- ret = k3_udma_glue_enable_tx_chn(common->tx_chns[i].tx_chn); +- if (ret) +- return ret; +- napi_enable(&common->tx_chns[i].napi_tx); ++ ret = k3_udma_glue_enable_rx_chn(common->rx_chns.rx_chn); ++ if (ret) { ++ dev_err(common->dev, "couldn't enable rx chn: %d\n", ret); ++ goto fail_rx; ++ } ++ ++ for (tx = 0; tx < common->tx_ch_num; tx++) { ++ ret = k3_udma_glue_enable_tx_chn(common->tx_chns[tx].tx_chn); ++ if (ret) { ++ dev_err(common->dev, "couldn't enable tx chn %d: %d\n", ++ tx, ret); ++ tx--; ++ goto fail_tx; ++ } ++ napi_enable(&common->tx_chns[tx].napi_tx); + } + + napi_enable(&common->napi_rx); +@@ -468,10 +556,22 @@ + + dev_dbg(common->dev, "cpsw_nuss started\n"); + return 0; +-} + +-static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma); +-static void am65_cpsw_nuss_rx_cleanup(void *data, dma_addr_t desc_dma); ++fail_tx: ++ while (tx >= 0) { ++ napi_disable(&common->tx_chns[tx].napi_tx); ++ k3_udma_glue_disable_tx_chn(common->tx_chns[tx].tx_chn); ++ tx--; ++ } ++ ++ k3_udma_glue_disable_rx_chn(common->rx_chns.rx_chn); ++ ++fail_rx: ++ k3_udma_glue_reset_rx_chn(common->rx_chns.rx_chn, 0, ++ &common->rx_chns, ++ am65_cpsw_nuss_rx_cleanup, 0); ++ return ret; ++} + + static int am65_cpsw_nuss_common_stop(struct am65_cpsw_common *common) + { +@@ -496,8 +596,10 @@ + msecs_to_jiffies(1000)); + if (!i) + dev_err(common->dev, "tx timeout\n"); +- for (i = 0; i < common->tx_ch_num; i++) ++ for (i = 0; i < common->tx_ch_num; i++) { + napi_disable(&common->tx_chns[i].napi_tx); ++ hrtimer_cancel(&common->tx_chns[i].tx_hrtimer); ++ } + + for (i = 0; i < common->tx_ch_num; i++) { + k3_udma_glue_reset_tx_chn(common->tx_chns[i].tx_chn, +@@ -516,6 +618,7 @@ + } + + napi_disable(&common->napi_rx); ++ hrtimer_cancel(&common->rx_hrtimer); + + for (i = 0; i < AM65_CPSW_MAX_RX_FLOWS; i++) + k3_udma_glue_reset_rx_chn(common->rx_chns.rx_chn, i, +@@ -646,27 +749,6 @@ + return ret; + } + +-static void am65_cpsw_nuss_rx_cleanup(void *data, dma_addr_t desc_dma) +-{ +- struct am65_cpsw_rx_chn *rx_chn = data; +- struct cppi5_host_desc_t *desc_rx; +- struct sk_buff *skb; +- dma_addr_t buf_dma; +- u32 buf_dma_len; +- void **swdata; +- +- desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma); +- swdata = cppi5_hdesc_get_swdata(desc_rx); +- skb = *swdata; +- cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); +- k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma); +- +- dma_unmap_single(rx_chn->dma_dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE); +- k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx); +- +- dev_kfree_skb_any(skb); +-} +- + static void am65_cpsw_nuss_rx_ts(struct sk_buff *skb, u32 *psdata) + { + struct skb_shared_hwtstamps *ssh; +@@ -806,6 +888,15 @@ + return ret; + } + ++static enum hrtimer_restart am65_cpsw_nuss_rx_timer_callback(struct hrtimer *timer) ++{ ++ struct am65_cpsw_common *common = ++ container_of(timer, struct am65_cpsw_common, rx_hrtimer); ++ ++ enable_irq(common->rx_chns.irq); ++ return HRTIMER_NORESTART; ++} ++ + static int am65_cpsw_nuss_rx_poll(struct napi_struct *napi_rx, int budget) + { + struct am65_cpsw_common *common = am65_cpsw_napi_to_common(napi_rx); +@@ -833,63 +924,19 @@ + if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) { + if (common->rx_irq_disabled) { + common->rx_irq_disabled = false; +- enable_irq(common->rx_chns.irq); ++ if (unlikely(common->rx_pace_timeout)) { ++ hrtimer_start(&common->rx_hrtimer, ++ ns_to_ktime(common->rx_pace_timeout), ++ HRTIMER_MODE_REL_PINNED); ++ } else { ++ enable_irq(common->rx_chns.irq); ++ } + } + } + + return num_rx; + } + +-static void am65_cpsw_nuss_xmit_free(struct am65_cpsw_tx_chn *tx_chn, +- struct cppi5_host_desc_t *desc) +-{ +- struct cppi5_host_desc_t *first_desc, *next_desc; +- dma_addr_t buf_dma, next_desc_dma; +- u32 buf_dma_len; +- +- first_desc = desc; +- next_desc = first_desc; +- +- cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len); +- k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma); +- +- dma_unmap_single(tx_chn->dma_dev, buf_dma, buf_dma_len, DMA_TO_DEVICE); +- +- next_desc_dma = cppi5_hdesc_get_next_hbdesc(first_desc); +- k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &next_desc_dma); +- while (next_desc_dma) { +- next_desc = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, +- next_desc_dma); +- cppi5_hdesc_get_obuf(next_desc, &buf_dma, &buf_dma_len); +- k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma); +- +- dma_unmap_page(tx_chn->dma_dev, buf_dma, buf_dma_len, +- DMA_TO_DEVICE); +- +- next_desc_dma = cppi5_hdesc_get_next_hbdesc(next_desc); +- k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &next_desc_dma); +- +- k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc); +- } +- +- k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc); +-} +- +-static void am65_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma) +-{ +- struct am65_cpsw_tx_chn *tx_chn = data; +- struct cppi5_host_desc_t *desc_tx; +- struct sk_buff *skb; +- void **swdata; +- +- desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma); +- swdata = cppi5_hdesc_get_swdata(desc_tx); +- skb = *(swdata); +- am65_cpsw_nuss_xmit_free(tx_chn, desc_tx); +- +- dev_kfree_skb_any(skb); +-} +- + static struct sk_buff * + am65_cpsw_nuss_tx_compl_packet(struct am65_cpsw_tx_chn *tx_chn, + dma_addr_t desc_dma) +@@ -939,7 +986,7 @@ + } + + static int am65_cpsw_nuss_tx_compl_packets(struct am65_cpsw_common *common, +- int chn, unsigned int budget) ++ int chn, unsigned int budget, bool *tdown) + { + struct device *dev = common->dev; + struct am65_cpsw_tx_chn *tx_chn; +@@ -962,6 +1009,7 @@ + if (cppi5_desc_is_tdcm(desc_dma)) { + if (atomic_dec_and_test(&common->tdown_cnt)) + complete(&common->tdown_complete); ++ *tdown = true; + break; + } + +@@ -984,7 +1032,7 @@ + } + + static int am65_cpsw_nuss_tx_compl_packets_2g(struct am65_cpsw_common *common, +- int chn, unsigned int budget) ++ int chn, unsigned int budget, bool *tdown) + { + struct device *dev = common->dev; + struct am65_cpsw_tx_chn *tx_chn; +@@ -1005,6 +1053,7 @@ + if (cppi5_desc_is_tdcm(desc_dma)) { + if (atomic_dec_and_test(&common->tdown_cnt)) + complete(&common->tdown_complete); ++ *tdown = true; + break; + } + +@@ -1030,21 +1079,40 @@ + return num_tx; + } + ++static enum hrtimer_restart am65_cpsw_nuss_tx_timer_callback(struct hrtimer *timer) ++{ ++ struct am65_cpsw_tx_chn *tx_chns = ++ container_of(timer, struct am65_cpsw_tx_chn, tx_hrtimer); ++ ++ enable_irq(tx_chns->irq); ++ return HRTIMER_NORESTART; ++} ++ + static int am65_cpsw_nuss_tx_poll(struct napi_struct *napi_tx, int budget) + { + struct am65_cpsw_tx_chn *tx_chn = am65_cpsw_napi_to_tx_chn(napi_tx); ++ bool tdown = false; + int num_tx; + + if (AM65_CPSW_IS_CPSW2G(tx_chn->common)) +- num_tx = am65_cpsw_nuss_tx_compl_packets_2g(tx_chn->common, tx_chn->id, budget); ++ num_tx = am65_cpsw_nuss_tx_compl_packets_2g(tx_chn->common, tx_chn->id, ++ budget, &tdown); + else +- num_tx = am65_cpsw_nuss_tx_compl_packets(tx_chn->common, tx_chn->id, budget); ++ num_tx = am65_cpsw_nuss_tx_compl_packets(tx_chn->common, ++ tx_chn->id, budget, &tdown); + + if (num_tx >= budget) + return budget; + +- if (napi_complete_done(napi_tx, num_tx)) +- enable_irq(tx_chn->irq); ++ if (napi_complete_done(napi_tx, num_tx)) { ++ if (unlikely(tx_chn->tx_pace_timeout && !tdown)) { ++ hrtimer_start(&tx_chn->tx_hrtimer, ++ ns_to_ktime(tx_chn->tx_pace_timeout), ++ HRTIMER_MODE_REL_PINNED); ++ } else { ++ enable_irq(tx_chn->irq); ++ } ++ } + + return 0; + } +@@ -1588,10 +1656,10 @@ + + /* rx_pause/tx_pause */ + if (rx_pause) +- mac_control |= CPSW_SL_CTL_RX_FLOW_EN; ++ mac_control |= CPSW_SL_CTL_TX_FLOW_EN; + + if (tx_pause) +- mac_control |= CPSW_SL_CTL_TX_FLOW_EN; ++ mac_control |= CPSW_SL_CTL_RX_FLOW_EN; + + cpsw_sl_ctl_set(port->slave.mac_sl, mac_control); + +@@ -1676,6 +1744,8 @@ + + netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx, + am65_cpsw_nuss_tx_poll); ++ hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); ++ tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback; + + ret = devm_request_irq(dev, tx_chn->irq, + am65_cpsw_nuss_tx_irq, +@@ -1901,6 +1971,8 @@ + + netif_napi_add(common->dma_ndev, &common->napi_rx, + am65_cpsw_nuss_rx_poll); ++ hrtimer_init(&common->rx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); ++ common->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback; + + ret = devm_request_irq(dev, rx_chn->irq, + am65_cpsw_nuss_rx_irq, +@@ -2098,6 +2170,9 @@ + dev_err(dev, "Use random MAC address\n"); + } + } ++ ++ /* Reset all Queue priorities to 0 */ ++ writel(0, port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP); + } + of_node_put(node); + +@@ -2162,6 +2237,8 @@ + ndev_priv = netdev_priv(port->ndev); + ndev_priv->port = port; + ndev_priv->msg_enable = AM65_CPSW_DEBUG; ++ mutex_init(&ndev_priv->mm_lock); ++ port->qos.link_speed = SPEED_UNKNOWN; + SET_NETDEV_DEV(port->ndev, dev); + + eth_hw_addr_set(port->ndev, port->slave.mac_addr); +@@ -2898,7 +2975,7 @@ + + common->rx_flow_id_base = -1; + init_completion(&common->tdown_complete); +- common->tx_ch_num = 1; ++ common->tx_ch_num = AM65_CPSW_DEFAULT_TX_CHNS; + common->pf_p0_rx_ptype_rrobin = false; + common->default_vlan = 1; + +@@ -3000,7 +3077,7 @@ + return ret; + } + +-static int am65_cpsw_nuss_remove(struct platform_device *pdev) ++static void am65_cpsw_nuss_remove(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct am65_cpsw_common *common; +@@ -3009,8 +3086,14 @@ + common = dev_get_drvdata(dev); + + ret = pm_runtime_resume_and_get(&pdev->dev); +- if (ret < 0) +- return ret; ++ if (ret < 0) { ++ /* Note, if this error path is taken, we're leaking some ++ * resources. ++ */ ++ dev_err(&pdev->dev, "Failed to resume device (%pe)\n", ++ ERR_PTR(ret)); ++ return; ++ } + + am65_cpsw_unregister_devlink(common); + am65_cpsw_unregister_notifiers(common); +@@ -3028,7 +3111,6 @@ + + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); +- return 0; + } + + static int am65_cpsw_nuss_suspend(struct device *dev) +@@ -3128,7 +3210,7 @@ + .pm = &am65_cpsw_nuss_dev_pm_ops, + }, + .probe = am65_cpsw_nuss_probe, +- .remove = am65_cpsw_nuss_remove, ++ .remove_new = am65_cpsw_nuss_remove, + }; + + module_platform_driver(am65_cpsw_nuss_driver); +diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h 2024-03-28 11:26:09.901017460 -0400 +@@ -75,6 +75,8 @@ + struct k3_cppi_desc_pool *desc_pool; + struct k3_udma_glue_tx_channel *tx_chn; + spinlock_t lock; /* protect TX rings in multi-port mode */ ++ struct hrtimer tx_hrtimer; ++ unsigned long tx_pace_timeout; + int irq; + u32 id; + u32 descs_num; +@@ -138,6 +140,8 @@ + struct napi_struct napi_rx; + + bool rx_irq_disabled; ++ struct hrtimer rx_hrtimer; ++ unsigned long rx_pace_timeout; + + u32 nuss_ver; + u32 cpsw_ver; +@@ -145,6 +149,7 @@ + bool pf_p0_rx_ptype_rrobin; + struct am65_cpts *cpts; + int est_enabled; ++ bool iet_enabled; + + bool is_emac_mode; + u16 br_members; +@@ -170,6 +175,10 @@ + struct am65_cpsw_port *port; + struct am65_cpsw_ndev_stats __percpu *stats; + bool offload_fwd_mark; ++ /* Serialize access to MAC Merge state between ethtool requests ++ * and link state updates ++ */ ++ struct mutex mm_lock; + }; + + #define am65_ndev_to_priv(ndev) \ +diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c +--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c 2024-03-28 11:26:09.901017460 -0400 +@@ -4,10 +4,13 @@ + * + * quality of service module includes: + * Enhanced Scheduler Traffic (EST - P802.1Qbv/D2.2) ++ * Interspersed Express Traffic (IET - P802.3br/D2.0) + */ + + #include ++#include + #include ++#include + #include + + #include "am65-cpsw-nuss.h" +@@ -15,40 +18,7 @@ + #include "am65-cpts.h" + #include "cpsw_ale.h" + +-#define AM65_CPSW_REG_CTL 0x004 +-#define AM65_CPSW_PN_REG_CTL 0x004 +-#define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 +-#define AM65_CPSW_PN_REG_EST_CTL 0x060 +-#define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) +- +-/* AM65_CPSW_REG_CTL register fields */ +-#define AM65_CPSW_CTL_EST_EN BIT(18) +- +-/* AM65_CPSW_PN_REG_CTL register fields */ +-#define AM65_CPSW_PN_CTL_EST_PORT_EN BIT(17) +- +-/* AM65_CPSW_PN_REG_EST_CTL register fields */ +-#define AM65_CPSW_PN_EST_ONEBUF BIT(0) +-#define AM65_CPSW_PN_EST_BUFSEL BIT(1) +-#define AM65_CPSW_PN_EST_TS_EN BIT(2) +-#define AM65_CPSW_PN_EST_TS_FIRST BIT(3) +-#define AM65_CPSW_PN_EST_ONEPRI BIT(4) +-#define AM65_CPSW_PN_EST_TS_PRI_MSK GENMASK(7, 5) +- +-/* AM65_CPSW_PN_REG_FIFO_STATUS register fields */ +-#define AM65_CPSW_PN_FST_TX_PRI_ACTIVE_MSK GENMASK(7, 0) +-#define AM65_CPSW_PN_FST_TX_E_MAC_ALLOW_MSK GENMASK(15, 8) +-#define AM65_CPSW_PN_FST_EST_CNT_ERR BIT(16) +-#define AM65_CPSW_PN_FST_EST_ADD_ERR BIT(17) +-#define AM65_CPSW_PN_FST_EST_BUFACT BIT(18) +- +-/* EST FETCH COMMAND RAM */ +-#define AM65_CPSW_FETCH_RAM_CMD_NUM 0x80 +-#define AM65_CPSW_FETCH_CNT_MSK GENMASK(21, 8) +-#define AM65_CPSW_FETCH_CNT_MAX (AM65_CPSW_FETCH_CNT_MSK >> 8) +-#define AM65_CPSW_FETCH_CNT_OFFSET 8 +-#define AM65_CPSW_FETCH_ALLOW_MSK GENMASK(7, 0) +-#define AM65_CPSW_FETCH_ALLOW_MAX AM65_CPSW_FETCH_ALLOW_MSK ++#define TO_MBPS(x) DIV_ROUND_UP((x), BYTES_PER_MBIT) + + enum timer_act { + TACT_PROG, /* need program timer */ +@@ -56,6 +26,412 @@ + TACT_SKIP_PROG, /* just buffer can be updated */ + }; + ++static void am65_cpsw_iet_change_preemptible_tcs(struct am65_cpsw_port *port, u8 preemptible_tcs); ++ ++static u32 ++am65_cpsw_qos_tx_rate_calc(u32 rate_mbps, unsigned long bus_freq) ++{ ++ u32 ir; ++ ++ bus_freq /= 1000000; ++ ir = DIV_ROUND_UP(((u64)rate_mbps * 32768), bus_freq); ++ return ir; ++} ++ ++static void am65_cpsw_tx_pn_shaper_reset(struct am65_cpsw_port *port) ++{ ++ int prio; ++ ++ for (prio = 0; prio < AM65_CPSW_PN_FIFO_PRIO_NUM; prio++) { ++ writel(0, port->port_base + AM65_CPSW_PN_REG_PRI_CIR(prio)); ++ writel(0, port->port_base + AM65_CPSW_PN_REG_PRI_EIR(prio)); ++ } ++} ++ ++static void am65_cpsw_tx_pn_shaper_apply(struct am65_cpsw_port *port) ++{ ++ struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; ++ struct am65_cpsw_common *common = port->common; ++ struct tc_mqprio_qopt_offload *mqprio; ++ bool enable, shaper_susp = false; ++ u32 rate_mbps; ++ int tc, prio; ++ ++ mqprio = &p_mqprio->mqprio_hw; ++ /* takes care of no link case as well */ ++ if (p_mqprio->max_rate_total > port->qos.link_speed) ++ shaper_susp = true; ++ ++ am65_cpsw_tx_pn_shaper_reset(port); ++ ++ enable = p_mqprio->shaper_en && !shaper_susp; ++ if (!enable) ++ return; ++ ++ /* Rate limit is specified per Traffic Class but ++ * for CPSW, rate limit can be applied per priority ++ * at port FIFO. ++ * ++ * We have assigned the same priority (TCn) to all queues ++ * of a Traffic Class so they share the same shaper ++ * bandwidth. ++ */ ++ for (tc = 0; tc < mqprio->qopt.num_tc; tc++) { ++ prio = tc; ++ ++ rate_mbps = TO_MBPS(mqprio->min_rate[tc]); ++ rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps, ++ common->bus_freq); ++ writel(rate_mbps, ++ port->port_base + AM65_CPSW_PN_REG_PRI_CIR(prio)); ++ ++ rate_mbps = 0; ++ ++ if (mqprio->max_rate[tc]) { ++ rate_mbps = mqprio->max_rate[tc] - mqprio->min_rate[tc]; ++ rate_mbps = TO_MBPS(rate_mbps); ++ rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps, ++ common->bus_freq); ++ } ++ ++ writel(rate_mbps, ++ port->port_base + AM65_CPSW_PN_REG_PRI_EIR(prio)); ++ } ++} ++ ++static int am65_cpsw_mqprio_verify_shaper(struct am65_cpsw_port *port, ++ struct tc_mqprio_qopt_offload *mqprio) ++{ ++ struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; ++ struct netlink_ext_ack *extack = mqprio->extack; ++ u64 min_rate_total = 0, max_rate_total = 0; ++ u32 min_rate_msk = 0, max_rate_msk = 0; ++ bool has_min_rate, has_max_rate; ++ int num_tc, i; ++ ++ if (!(mqprio->flags & TC_MQPRIO_F_SHAPER)) ++ return 0; ++ ++ if (mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE) ++ return 0; ++ ++ has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE); ++ has_max_rate = !!(mqprio->flags & TC_MQPRIO_F_MAX_RATE); ++ ++ if (!has_min_rate && has_max_rate) { ++ NL_SET_ERR_MSG_MOD(extack, "min_rate is required with max_rate"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (!has_min_rate) ++ return 0; ++ ++ num_tc = mqprio->qopt.num_tc; ++ ++ for (i = num_tc - 1; i >= 0; i--) { ++ u32 ch_msk; ++ ++ if (mqprio->min_rate[i]) ++ min_rate_msk |= BIT(i); ++ min_rate_total += mqprio->min_rate[i]; ++ ++ if (has_max_rate) { ++ if (mqprio->max_rate[i]) ++ max_rate_msk |= BIT(i); ++ max_rate_total += mqprio->max_rate[i]; ++ ++ if (!mqprio->min_rate[i] && mqprio->max_rate[i]) { ++ NL_SET_ERR_MSG_FMT_MOD(extack, ++ "TX tc%d rate max>0 but min=0", ++ i); ++ return -EINVAL; ++ } ++ ++ if (mqprio->max_rate[i] && ++ mqprio->max_rate[i] < mqprio->min_rate[i]) { ++ NL_SET_ERR_MSG_FMT_MOD(extack, ++ "TX tc%d rate min(%llu)>max(%llu)", ++ i, mqprio->min_rate[i], ++ mqprio->max_rate[i]); ++ return -EINVAL; ++ } ++ } ++ ++ ch_msk = GENMASK(num_tc - 1, i); ++ if ((min_rate_msk & BIT(i)) && (min_rate_msk ^ ch_msk)) { ++ NL_SET_ERR_MSG_FMT_MOD(extack, ++ "Min rate must be set sequentially hi->lo tx_rate_msk%x", ++ min_rate_msk); ++ return -EINVAL; ++ } ++ ++ if ((max_rate_msk & BIT(i)) && (max_rate_msk ^ ch_msk)) { ++ NL_SET_ERR_MSG_FMT_MOD(extack, ++ "Max rate must be set sequentially hi->lo tx_rate_msk%x", ++ max_rate_msk); ++ return -EINVAL; ++ } ++ } ++ ++ min_rate_total = TO_MBPS(min_rate_total); ++ max_rate_total = TO_MBPS(max_rate_total); ++ ++ p_mqprio->shaper_en = true; ++ p_mqprio->max_rate_total = max_t(u64, min_rate_total, max_rate_total); ++ ++ return 0; ++} ++ ++static void am65_cpsw_reset_tc_mqprio(struct net_device *ndev) ++{ ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; ++ ++ p_mqprio->shaper_en = false; ++ p_mqprio->max_rate_total = 0; ++ ++ am65_cpsw_tx_pn_shaper_reset(port); ++ netdev_reset_tc(ndev); ++ ++ /* Reset all Queue priorities to 0 */ ++ writel(0, port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP); ++ ++ am65_cpsw_iet_change_preemptible_tcs(port, 0); ++} ++ ++static int am65_cpsw_setup_mqprio(struct net_device *ndev, void *type_data) ++{ ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio; ++ struct tc_mqprio_qopt_offload *mqprio = type_data; ++ struct am65_cpsw_common *common = port->common; ++ struct tc_mqprio_qopt *qopt = &mqprio->qopt; ++ int i, tc, offset, count, prio, ret; ++ u8 num_tc = qopt->num_tc; ++ u32 tx_prio_map = 0; ++ ++ memcpy(&p_mqprio->mqprio_hw, mqprio, sizeof(*mqprio)); ++ ++ ret = pm_runtime_get_sync(common->dev); ++ if (ret < 0) { ++ pm_runtime_put_noidle(common->dev); ++ return ret; ++ } ++ ++ if (!num_tc) { ++ am65_cpsw_reset_tc_mqprio(ndev); ++ ret = 0; ++ goto exit_put; ++ } ++ ++ ret = am65_cpsw_mqprio_verify_shaper(port, mqprio); ++ if (ret) ++ goto exit_put; ++ ++ netdev_set_num_tc(ndev, num_tc); ++ ++ /* Multiple Linux priorities can map to a Traffic Class ++ * A Traffic Class can have multiple contiguous Queues, ++ * Queues get mapped to Channels (thread_id), ++ * if not VLAN tagged, thread_id is used as packet_priority ++ * if VLAN tagged. VLAN priority is used as packet_priority ++ * packet_priority gets mapped to header_priority in p0_rx_pri_map, ++ * header_priority gets mapped to switch_priority in pn_tx_pri_map. ++ * As p0_rx_pri_map is left at defaults (0x76543210), we can ++ * assume that Queue_n gets mapped to header_priority_n. We can then ++ * set the switch priority in pn_tx_pri_map. ++ */ ++ ++ for (tc = 0; tc < num_tc; tc++) { ++ prio = tc; ++ ++ /* For simplicity we assign the same priority (TCn) to ++ * all queues of a Traffic Class. ++ */ ++ for (i = qopt->offset[tc]; i < qopt->offset[tc] + qopt->count[tc]; i++) ++ tx_prio_map |= prio << (4 * i); ++ ++ count = qopt->count[tc]; ++ offset = qopt->offset[tc]; ++ netdev_set_tc_queue(ndev, tc, count, offset); ++ } ++ ++ writel(tx_prio_map, port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP); ++ ++ am65_cpsw_tx_pn_shaper_apply(port); ++ am65_cpsw_iet_change_preemptible_tcs(port, mqprio->preemptible_tcs); ++ ++exit_put: ++ pm_runtime_put(common->dev); ++ ++ return ret; ++} ++ ++static int am65_cpsw_iet_set_verify_timeout_count(struct am65_cpsw_port *port) ++{ ++ int verify_time_ms = port->qos.iet.verify_time_ms; ++ u32 val; ++ ++ /* The number of wireside clocks contained in the verify ++ * timeout counter. The default is 0x1312d0 ++ * (10ms at 125Mhz in 1G mode). ++ */ ++ val = 125 * HZ_PER_MHZ; /* assuming 125MHz wireside clock */ ++ ++ val /= MILLIHZ_PER_HZ; /* count per ms timeout */ ++ val *= verify_time_ms; /* count for timeout ms */ ++ ++ if (val > AM65_CPSW_PN_MAC_VERIFY_CNT_MASK) ++ return -EINVAL; ++ ++ writel(val, port->port_base + AM65_CPSW_PN_REG_IET_VERIFY); ++ ++ return 0; ++} ++ ++static int am65_cpsw_iet_verify_wait(struct am65_cpsw_port *port) ++{ ++ u32 ctrl, status; ++ int try; ++ ++ try = 20; ++ do { ++ /* Reset the verify state machine by writing 1 ++ * to LINKFAIL ++ */ ++ ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ctrl |= AM65_CPSW_PN_IET_MAC_LINKFAIL; ++ writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ++ /* Clear MAC_LINKFAIL bit to start Verify. */ ++ ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ctrl &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL; ++ writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ ++ msleep(port->qos.iet.verify_time_ms); ++ ++ status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS); ++ if (status & AM65_CPSW_PN_MAC_VERIFIED) ++ return 0; ++ ++ if (status & AM65_CPSW_PN_MAC_VERIFY_FAIL) { ++ netdev_dbg(port->ndev, ++ "MAC Merge verify failed, trying again\n"); ++ continue; ++ } ++ ++ if (status & AM65_CPSW_PN_MAC_RESPOND_ERR) { ++ netdev_dbg(port->ndev, "MAC Merge respond error\n"); ++ return -ENODEV; ++ } ++ ++ if (status & AM65_CPSW_PN_MAC_VERIFY_ERR) { ++ netdev_dbg(port->ndev, "MAC Merge verify error\n"); ++ return -ENODEV; ++ } ++ } while (try-- > 0); ++ ++ netdev_dbg(port->ndev, "MAC Merge verify timeout\n"); ++ return -ETIMEDOUT; ++} ++ ++static void am65_cpsw_iet_set_preempt_mask(struct am65_cpsw_port *port, u8 preemptible_tcs) ++{ ++ u32 val; ++ ++ val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ val &= ~AM65_CPSW_PN_IET_MAC_PREMPT_MASK; ++ val |= AM65_CPSW_PN_IET_MAC_SET_PREEMPT(preemptible_tcs); ++ writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++} ++ ++/* enable common IET_ENABLE only if at least 1 port has rx IET enabled. ++ * UAPI doesn't allow tx enable without rx enable. ++ */ ++void am65_cpsw_iet_common_enable(struct am65_cpsw_common *common) ++{ ++ struct am65_cpsw_port *port; ++ bool rx_enable = false; ++ u32 val; ++ int i; ++ ++ for (i = 0; i < common->port_num; i++) { ++ port = &common->ports[i]; ++ val = readl(port->port_base + AM65_CPSW_PN_REG_CTL); ++ rx_enable = !!(val & AM65_CPSW_PN_CTL_IET_PORT_EN); ++ if (rx_enable) ++ break; ++ } ++ ++ val = readl(common->cpsw_base + AM65_CPSW_REG_CTL); ++ ++ if (rx_enable) ++ val |= AM65_CPSW_CTL_IET_EN; ++ else ++ val &= ~AM65_CPSW_CTL_IET_EN; ++ ++ writel(val, common->cpsw_base + AM65_CPSW_REG_CTL); ++ common->iet_enabled = rx_enable; ++} ++ ++/* CPSW does not have an IRQ to notify changes to the MAC Merge TX status ++ * (active/inactive), but the preemptible traffic classes should only be ++ * committed to hardware once TX is active. Resort to polling. ++ */ ++void am65_cpsw_iet_commit_preemptible_tcs(struct am65_cpsw_port *port) ++{ ++ u8 preemptible_tcs; ++ int err; ++ u32 val; ++ ++ if (port->qos.link_speed == SPEED_UNKNOWN) ++ return; ++ ++ val = readl(port->port_base + AM65_CPSW_PN_REG_CTL); ++ if (!(val & AM65_CPSW_PN_CTL_IET_PORT_EN)) ++ return; ++ ++ /* update common IET enable */ ++ am65_cpsw_iet_common_enable(port->common); ++ ++ /* update verify count */ ++ err = am65_cpsw_iet_set_verify_timeout_count(port); ++ if (err) { ++ netdev_err(port->ndev, "couldn't set verify count: %d\n", err); ++ return; ++ } ++ ++ val = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL); ++ if (!(val & AM65_CPSW_PN_IET_MAC_DISABLEVERIFY)) { ++ err = am65_cpsw_iet_verify_wait(port); ++ if (err) ++ return; ++ } ++ ++ preemptible_tcs = port->qos.iet.preemptible_tcs; ++ am65_cpsw_iet_set_preempt_mask(port, preemptible_tcs); ++} ++ ++static void am65_cpsw_iet_change_preemptible_tcs(struct am65_cpsw_port *port, u8 preemptible_tcs) ++{ ++ struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(port->ndev); ++ ++ port->qos.iet.preemptible_tcs = preemptible_tcs; ++ mutex_lock(&priv->mm_lock); ++ am65_cpsw_iet_commit_preemptible_tcs(port); ++ mutex_unlock(&priv->mm_lock); ++} ++ ++static void am65_cpsw_iet_link_state_update(struct net_device *ndev) ++{ ++ struct am65_cpsw_ndev_priv *priv = am65_ndev_to_priv(ndev); ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ ++ mutex_lock(&priv->mm_lock); ++ am65_cpsw_iet_commit_preemptible_tcs(port); ++ mutex_unlock(&priv->mm_lock); ++} ++ + static int am65_cpsw_port_est_enabled(struct am65_cpsw_port *port) + { + return port->qos.est_oper || port->qos.est_admin; +@@ -428,7 +804,7 @@ + am65_cpsw_timer_stop(ndev); + } + +-static void am65_cpsw_purge_est(struct net_device *ndev) ++static void am65_cpsw_taprio_destroy(struct net_device *ndev) + { + struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + +@@ -439,31 +815,74 @@ + + port->qos.est_oper = NULL; + port->qos.est_admin = NULL; ++ ++ am65_cpsw_reset_tc_mqprio(ndev); + } + +-static int am65_cpsw_configure_taprio(struct net_device *ndev, +- struct am65_cpsw_est *est_new) ++static void am65_cpsw_cp_taprio(struct tc_taprio_qopt_offload *from, ++ struct tc_taprio_qopt_offload *to) ++{ ++ int i; ++ ++ *to = *from; ++ for (i = 0; i < from->num_entries; i++) ++ to->entries[i] = from->entries[i]; ++} ++ ++static int am65_cpsw_taprio_replace(struct net_device *ndev, ++ struct tc_taprio_qopt_offload *taprio) + { + struct am65_cpsw_common *common = am65_ndev_to_common(ndev); ++ struct netlink_ext_ack *extack = taprio->mqprio.extack; ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + struct am65_cpts *cpts = common->cpts; +- int ret = 0, tact = TACT_PROG; ++ struct am65_cpsw_est *est_new; ++ int ret, tact; + +- am65_cpsw_est_update_state(ndev); ++ if (!netif_running(ndev)) { ++ NL_SET_ERR_MSG_MOD(extack, "interface is down, link speed unknown"); ++ return -ENETDOWN; ++ } + +- if (est_new->taprio.cmd == TAPRIO_CMD_DESTROY) { +- am65_cpsw_stop_est(ndev); +- return ret; ++ if (common->pf_p0_rx_ptype_rrobin) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "p0-rx-ptype-rrobin flag conflicts with taprio qdisc"); ++ return -EINVAL; + } + ++ if (port->qos.link_speed == SPEED_UNKNOWN) ++ return -ENOLINK; ++ ++ if (taprio->cycle_time_extension) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "cycle time extension not supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ est_new = devm_kzalloc(&ndev->dev, ++ struct_size(est_new, taprio.entries, taprio->num_entries), ++ GFP_KERNEL); ++ if (!est_new) ++ return -ENOMEM; ++ ++ ret = am65_cpsw_setup_mqprio(ndev, &taprio->mqprio); ++ if (ret) ++ return ret; ++ ++ am65_cpsw_cp_taprio(taprio, &est_new->taprio); ++ ++ am65_cpsw_est_update_state(ndev); ++ + ret = am65_cpsw_est_check_scheds(ndev, est_new); + if (ret < 0) +- return ret; ++ goto fail; + + tact = am65_cpsw_timer_act(ndev, est_new); + if (tact == TACT_NEED_STOP) { +- dev_err(&ndev->dev, +- "Can't toggle estf timer, stop taprio first"); +- return -EINVAL; ++ NL_SET_ERR_MSG_MOD(extack, ++ "Can't toggle estf timer, stop taprio first"); ++ ret = -EINVAL; ++ goto fail; + } + + if (tact == TACT_PROG) +@@ -476,62 +895,26 @@ + am65_cpsw_est_set_sched_list(ndev, est_new); + am65_cpsw_port_est_assign_buf_num(ndev, est_new->buf); + +- am65_cpsw_est_set(ndev, est_new->taprio.cmd == TAPRIO_CMD_REPLACE); ++ am65_cpsw_est_set(ndev, 1); + + if (tact == TACT_PROG) { + ret = am65_cpsw_timer_set(ndev, est_new); + if (ret) { +- dev_err(&ndev->dev, "Failed to set cycle time"); +- return ret; ++ NL_SET_ERR_MSG_MOD(extack, ++ "Failed to set cycle time"); ++ goto fail; + } + } + +- return ret; +-} +- +-static void am65_cpsw_cp_taprio(struct tc_taprio_qopt_offload *from, +- struct tc_taprio_qopt_offload *to) +-{ +- int i; +- +- *to = *from; +- for (i = 0; i < from->num_entries; i++) +- to->entries[i] = from->entries[i]; +-} +- +-static int am65_cpsw_set_taprio(struct net_device *ndev, void *type_data) +-{ +- struct am65_cpsw_port *port = am65_ndev_to_port(ndev); +- struct tc_taprio_qopt_offload *taprio = type_data; +- struct am65_cpsw_est *est_new; +- int ret = 0; +- +- if (taprio->cycle_time_extension) { +- dev_err(&ndev->dev, "Failed to set cycle time extension"); +- return -EOPNOTSUPP; +- } +- +- est_new = devm_kzalloc(&ndev->dev, +- struct_size(est_new, taprio.entries, taprio->num_entries), +- GFP_KERNEL); +- if (!est_new) +- return -ENOMEM; +- +- am65_cpsw_cp_taprio(taprio, &est_new->taprio); +- ret = am65_cpsw_configure_taprio(ndev, est_new); +- if (!ret) { +- if (taprio->cmd == TAPRIO_CMD_REPLACE) { +- devm_kfree(&ndev->dev, port->qos.est_admin); ++ devm_kfree(&ndev->dev, port->qos.est_admin); ++ port->qos.est_admin = est_new; ++ am65_cpsw_iet_change_preemptible_tcs(port, taprio->mqprio.preemptible_tcs); + +- port->qos.est_admin = est_new; +- } else { +- devm_kfree(&ndev->dev, est_new); +- am65_cpsw_purge_est(ndev); +- } +- } else { +- devm_kfree(&ndev->dev, est_new); +- } ++ return 0; + ++fail: ++ am65_cpsw_reset_tc_mqprio(ndev); ++ devm_kfree(&ndev->dev, est_new); + return ret; + } + +@@ -541,7 +924,6 @@ + ktime_t cur_time; + s64 delta; + +- port->qos.link_speed = link_speed; + if (!am65_cpsw_port_est_enabled(port)) + return; + +@@ -558,37 +940,26 @@ + return; + + purge_est: +- am65_cpsw_purge_est(ndev); ++ am65_cpsw_taprio_destroy(ndev); + } + + static int am65_cpsw_setup_taprio(struct net_device *ndev, void *type_data) + { +- struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + struct tc_taprio_qopt_offload *taprio = type_data; +- struct am65_cpsw_common *common = port->common; +- +- if (taprio->cmd != TAPRIO_CMD_REPLACE && +- taprio->cmd != TAPRIO_CMD_DESTROY) +- return -EOPNOTSUPP; +- +- if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) +- return -ENODEV; ++ int err = 0; + +- if (!netif_running(ndev)) { +- dev_err(&ndev->dev, "interface is down, link speed unknown\n"); +- return -ENETDOWN; +- } +- +- if (common->pf_p0_rx_ptype_rrobin) { +- dev_err(&ndev->dev, +- "p0-rx-ptype-rrobin flag conflicts with taprio qdisc\n"); +- return -EINVAL; ++ switch (taprio->cmd) { ++ case TAPRIO_CMD_REPLACE: ++ err = am65_cpsw_taprio_replace(ndev, taprio); ++ break; ++ case TAPRIO_CMD_DESTROY: ++ am65_cpsw_taprio_destroy(ndev); ++ break; ++ default: ++ err = -EOPNOTSUPP; + } + +- if (port->qos.link_speed == SPEED_UNKNOWN) +- return -ENOLINK; +- +- return am65_cpsw_set_taprio(ndev, type_data); ++ return err; + } + + static int am65_cpsw_tc_query_caps(struct net_device *ndev, void *type_data) +@@ -596,12 +967,17 @@ + struct tc_query_caps_base *base = type_data; + + switch (base->type) { ++ case TC_SETUP_QDISC_MQPRIO: { ++ struct tc_mqprio_caps *caps = base->caps; ++ ++ caps->validate_queue_counts = true; ++ ++ return 0; ++ } ++ + case TC_SETUP_QDISC_TAPRIO: { + struct tc_taprio_caps *caps = base->caps; + +- if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) +- return -EOPNOTSUPP; +- + caps->gate_mask_per_txq = true; + + return 0; +@@ -787,55 +1163,6 @@ + port, port, true); + } + +-int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, +- void *type_data) +-{ +- switch (type) { +- case TC_QUERY_CAPS: +- return am65_cpsw_tc_query_caps(ndev, type_data); +- case TC_SETUP_QDISC_TAPRIO: +- return am65_cpsw_setup_taprio(ndev, type_data); +- case TC_SETUP_BLOCK: +- return am65_cpsw_qos_setup_tc_block(ndev, type_data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed) +-{ +- struct am65_cpsw_port *port = am65_ndev_to_port(ndev); +- +- if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) +- return; +- +- am65_cpsw_est_link_up(ndev, link_speed); +- port->qos.link_down_time = 0; +-} +- +-void am65_cpsw_qos_link_down(struct net_device *ndev) +-{ +- struct am65_cpsw_port *port = am65_ndev_to_port(ndev); +- +- if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) +- return; +- +- if (!port->qos.link_down_time) +- port->qos.link_down_time = ktime_get(); +- +- port->qos.link_speed = SPEED_UNKNOWN; +-} +- +-static u32 +-am65_cpsw_qos_tx_rate_calc(u32 rate_mbps, unsigned long bus_freq) +-{ +- u32 ir; +- +- bus_freq /= 1000000; +- ir = DIV_ROUND_UP(((u64)rate_mbps * 32768), bus_freq); +- return ir; +-} +- + static void + am65_cpsw_qos_tx_p0_rate_apply(struct am65_cpsw_common *common, + int tx_ch, u32 rate_mbps) +@@ -937,3 +1264,44 @@ + host->port_base + AM65_CPSW_PN_REG_PRI_CIR(tx_ch)); + } + } ++ ++int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, ++ void *type_data) ++{ ++ switch (type) { ++ case TC_QUERY_CAPS: ++ return am65_cpsw_tc_query_caps(ndev, type_data); ++ case TC_SETUP_QDISC_TAPRIO: ++ return am65_cpsw_setup_taprio(ndev, type_data); ++ case TC_SETUP_QDISC_MQPRIO: ++ return am65_cpsw_setup_mqprio(ndev, type_data); ++ case TC_SETUP_BLOCK: ++ return am65_cpsw_qos_setup_tc_block(ndev, type_data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed) ++{ ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ ++ port->qos.link_speed = link_speed; ++ am65_cpsw_tx_pn_shaper_apply(port); ++ am65_cpsw_iet_link_state_update(ndev); ++ ++ am65_cpsw_est_link_up(ndev, link_speed); ++ port->qos.link_down_time = 0; ++} ++ ++void am65_cpsw_qos_link_down(struct net_device *ndev) ++{ ++ struct am65_cpsw_port *port = am65_ndev_to_port(ndev); ++ ++ port->qos.link_speed = SPEED_UNKNOWN; ++ am65_cpsw_tx_pn_shaper_apply(port); ++ am65_cpsw_iet_link_state_update(ndev); ++ ++ if (!port->qos.link_down_time) ++ port->qos.link_down_time = ktime_get(); ++} +diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-qos.h b/drivers/net/ethernet/ti/am65-cpsw-qos.h +--- a/drivers/net/ethernet/ti/am65-cpsw-qos.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/am65-cpsw-qos.h 2024-03-28 11:26:09.901017460 -0400 +@@ -9,6 +9,7 @@ + #include + + struct am65_cpsw_common; ++struct am65_cpsw_port; + + struct am65_cpsw_est { + int buf; +@@ -16,6 +17,18 @@ + struct tc_taprio_qopt_offload taprio; + }; + ++struct am65_cpsw_mqprio { ++ struct tc_mqprio_qopt_offload mqprio_hw; ++ u64 max_rate_total; ++ bool shaper_en; ++}; ++ ++struct am65_cpsw_iet { ++ u8 preemptible_tcs; ++ u32 original_max_blks; ++ int verify_time_ms; ++}; ++ + struct am65_cpsw_ale_ratelimit { + unsigned long cookie; + u64 rate_packet_ps; +@@ -26,16 +39,189 @@ + struct am65_cpsw_est *est_oper; + ktime_t link_down_time; + int link_speed; ++ struct am65_cpsw_mqprio mqprio; ++ struct am65_cpsw_iet iet; + + struct am65_cpsw_ale_ratelimit ale_bc_ratelimit; + struct am65_cpsw_ale_ratelimit ale_mc_ratelimit; + }; + ++#define AM65_CPSW_REG_CTL 0x004 ++#define AM65_CPSW_PN_REG_CTL 0x004 ++#define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 ++#define AM65_CPSW_PN_REG_EST_CTL 0x060 ++#define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) ++#define AM65_CPSW_P0_REG_PRI_EIR(pri) (0x160 + 4 * (pri)) ++ ++#define AM65_CPSW_PN_REG_CTL 0x004 ++#define AM65_CPSW_PN_REG_TX_PRI_MAP 0x018 ++#define AM65_CPSW_PN_REG_RX_PRI_MAP 0x020 ++#define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 ++#define AM65_CPSW_PN_REG_EST_CTL 0x060 ++#define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) ++#define AM65_CPSW_PN_REG_PRI_EIR(pri) (0x160 + 4 * (pri)) ++ ++/* AM65_CPSW_REG_CTL register fields */ ++#define AM65_CPSW_CTL_EST_EN BIT(18) ++ ++/* AM65_CPSW_PN_REG_CTL register fields */ ++#define AM65_CPSW_PN_CTL_EST_PORT_EN BIT(17) ++ ++/* AM65_CPSW_PN_REG_EST_CTL register fields */ ++#define AM65_CPSW_PN_EST_ONEBUF BIT(0) ++#define AM65_CPSW_PN_EST_BUFSEL BIT(1) ++#define AM65_CPSW_PN_EST_TS_EN BIT(2) ++#define AM65_CPSW_PN_EST_TS_FIRST BIT(3) ++#define AM65_CPSW_PN_EST_ONEPRI BIT(4) ++#define AM65_CPSW_PN_EST_TS_PRI_MSK GENMASK(7, 5) ++ ++/* AM65_CPSW_PN_REG_FIFO_STATUS register fields */ ++#define AM65_CPSW_PN_FST_TX_PRI_ACTIVE_MSK GENMASK(7, 0) ++#define AM65_CPSW_PN_FST_TX_E_MAC_ALLOW_MSK GENMASK(15, 8) ++#define AM65_CPSW_PN_FST_EST_CNT_ERR BIT(16) ++#define AM65_CPSW_PN_FST_EST_ADD_ERR BIT(17) ++#define AM65_CPSW_PN_FST_EST_BUFACT BIT(18) ++ ++/* EST FETCH COMMAND RAM */ ++#define AM65_CPSW_FETCH_RAM_CMD_NUM 0x80 ++#define AM65_CPSW_FETCH_CNT_MSK GENMASK(21, 8) ++#define AM65_CPSW_FETCH_CNT_MAX (AM65_CPSW_FETCH_CNT_MSK >> 8) ++#define AM65_CPSW_FETCH_CNT_OFFSET 8 ++#define AM65_CPSW_FETCH_ALLOW_MSK GENMASK(7, 0) ++#define AM65_CPSW_FETCH_ALLOW_MAX AM65_CPSW_FETCH_ALLOW_MSK ++ ++/* number of priority queues per port FIFO */ ++#define AM65_CPSW_PN_FIFO_PRIO_NUM 8 ++ ++#if IS_ENABLED(CONFIG_TI_AM65_CPSW_QOS) + int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, + void *type_data); + void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed); + void am65_cpsw_qos_link_down(struct net_device *ndev); + int am65_cpsw_qos_ndo_tx_p0_set_maxrate(struct net_device *ndev, int queue, u32 rate_mbps); + void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common); ++void am65_cpsw_iet_commit_preemptible_tcs(struct am65_cpsw_port *port); ++void am65_cpsw_iet_common_enable(struct am65_cpsw_common *common); ++#else ++static inline int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, ++ enum tc_setup_type type, ++ void *type_data) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void am65_cpsw_qos_link_up(struct net_device *ndev, ++ int link_speed) ++{ } ++ ++static inline void am65_cpsw_qos_link_down(struct net_device *ndev) ++{ } ++ ++static inline int am65_cpsw_qos_ndo_tx_p0_set_maxrate(struct net_device *ndev, ++ int queue, ++ u32 rate_mbps) ++{ ++ return 0; ++} ++ ++static inline void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common) ++{ } ++static inline void am65_cpsw_iet_commit_preemptible_tcs(struct am65_cpsw_port *port) ++{ } ++static inline void am65_cpsw_iet_common_enable(struct am65_cpsw_common *common) ++{ } ++#endif ++ ++#define AM65_CPSW_REG_CTL 0x004 ++#define AM65_CPSW_PN_REG_CTL 0x004 ++#define AM65_CPSW_PN_REG_MAX_BLKS 0x008 ++#define AM65_CPSW_PN_REG_TX_PRI_MAP 0x018 ++#define AM65_CPSW_PN_REG_RX_PRI_MAP 0x020 ++#define AM65_CPSW_PN_REG_IET_CTRL 0x040 ++#define AM65_CPSW_PN_REG_IET_STATUS 0x044 ++#define AM65_CPSW_PN_REG_IET_VERIFY 0x048 ++#define AM65_CPSW_PN_REG_FIFO_STATUS 0x050 ++#define AM65_CPSW_PN_REG_EST_CTL 0x060 ++#define AM65_CPSW_PN_REG_PRI_CIR(pri) (0x140 + 4 * (pri)) ++#define AM65_CPSW_PN_REG_PRI_EIR(pri) (0x160 + 4 * (pri)) ++ ++/* AM65_CPSW_REG_CTL register fields */ ++#define AM65_CPSW_CTL_IET_EN BIT(17) ++#define AM65_CPSW_CTL_EST_EN BIT(18) ++ ++/* AM65_CPSW_PN_REG_CTL register fields */ ++#define AM65_CPSW_PN_CTL_IET_PORT_EN BIT(16) ++#define AM65_CPSW_PN_CTL_EST_PORT_EN BIT(17) ++ ++/* AM65_CPSW_PN_REG_EST_CTL register fields */ ++#define AM65_CPSW_PN_EST_ONEBUF BIT(0) ++#define AM65_CPSW_PN_EST_BUFSEL BIT(1) ++#define AM65_CPSW_PN_EST_TS_EN BIT(2) ++#define AM65_CPSW_PN_EST_TS_FIRST BIT(3) ++#define AM65_CPSW_PN_EST_ONEPRI BIT(4) ++#define AM65_CPSW_PN_EST_TS_PRI_MSK GENMASK(7, 5) ++ ++/* AM65_CPSW_PN_REG_IET_CTRL register fields */ ++#define AM65_CPSW_PN_IET_MAC_PENABLE BIT(0) ++#define AM65_CPSW_PN_IET_MAC_DISABLEVERIFY BIT(2) ++#define AM65_CPSW_PN_IET_MAC_LINKFAIL BIT(3) ++#define AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK GENMASK(10, 8) ++#define AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_OFFSET 8 ++#define AM65_CPSW_PN_IET_MAC_PREMPT_MASK GENMASK(23, 16) ++#define AM65_CPSW_PN_IET_MAC_PREMPT_OFFSET 16 ++ ++#define AM65_CPSW_PN_IET_MAC_SET_ADDFRAGSIZE(n) (((n) << AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_OFFSET) & \ ++ AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK) ++#define AM65_CPSW_PN_IET_MAC_GET_ADDFRAGSIZE(n) (((n) & AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK) >> \ ++ AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_OFFSET) ++#define AM65_CPSW_PN_IET_MAC_SET_PREEMPT(n) (((n) << AM65_CPSW_PN_IET_MAC_PREMPT_OFFSET) & \ ++ AM65_CPSW_PN_IET_MAC_PREMPT_MASK) ++#define AM65_CPSW_PN_IET_MAC_GET_PREEMPT(n) (((n) & AM65_CPSW_PN_IET_MAC_PREMPT_MASK) >> \ ++ AM65_CPSW_PN_IET_MAC_PREMPT_OFFSET) ++ ++/* AM65_CPSW_PN_REG_IET_STATUS register fields */ ++#define AM65_CPSW_PN_MAC_STATUS GENMASK(3, 0) ++#define AM65_CPSW_PN_MAC_VERIFIED BIT(0) ++#define AM65_CPSW_PN_MAC_VERIFY_FAIL BIT(1) ++#define AM65_CPSW_PN_MAC_RESPOND_ERR BIT(2) ++#define AM65_CPSW_PN_MAC_VERIFY_ERR BIT(3) ++ ++/* AM65_CPSW_PN_REG_IET_VERIFY register fields */ ++#define AM65_CPSW_PN_MAC_VERIFY_CNT_MASK GENMASK(23, 0) ++#define AM65_CPSW_PN_MAC_GET_VERIFY_CNT(n) ((n) & AM65_CPSW_PN_MAC_VERIFY_CNT_MASK) ++/* 10 msec converted to NSEC */ ++#define AM65_CPSW_IET_VERIFY_CNT_MS (10) ++#define AM65_CPSW_IET_VERIFY_CNT_NS (AM65_CPSW_IET_VERIFY_CNT_MS * \ ++ NSEC_PER_MSEC) ++ ++/* AM65_CPSW_PN_REG_FIFO_STATUS register fields */ ++#define AM65_CPSW_PN_FST_TX_PRI_ACTIVE_MSK GENMASK(7, 0) ++#define AM65_CPSW_PN_FST_TX_E_MAC_ALLOW_MSK GENMASK(15, 8) ++#define AM65_CPSW_PN_FST_EST_CNT_ERR BIT(16) ++#define AM65_CPSW_PN_FST_EST_ADD_ERR BIT(17) ++#define AM65_CPSW_PN_FST_EST_BUFACT BIT(18) ++ ++/* EST FETCH COMMAND RAM */ ++#define AM65_CPSW_FETCH_RAM_CMD_NUM 0x80 ++#define AM65_CPSW_FETCH_CNT_MSK GENMASK(21, 8) ++#define AM65_CPSW_FETCH_CNT_MAX (AM65_CPSW_FETCH_CNT_MSK >> 8) ++#define AM65_CPSW_FETCH_CNT_OFFSET 8 ++#define AM65_CPSW_FETCH_ALLOW_MSK GENMASK(7, 0) ++#define AM65_CPSW_FETCH_ALLOW_MAX AM65_CPSW_FETCH_ALLOW_MSK ++ ++/* AM65_CPSW_PN_REG_MAX_BLKS fields for IET and No IET cases */ ++/* 7 blocks for pn_rx_max_blks, 13 for pn_tx_max_blks*/ ++#define AM65_CPSW_PN_TX_RX_MAX_BLKS_IET 0xD07 ++ ++/* Slave IET Stats. register offsets */ ++#define AM65_CPSW_STATN_IET_RX_ASSEMBLY_ERROR 0x140 ++#define AM65_CPSW_STATN_IET_RX_ASSEMBLY_OK 0x144 ++#define AM65_CPSW_STATN_IET_RX_SMD_ERROR 0x148 ++#define AM65_CPSW_STATN_IET_RX_FRAG 0x14c ++#define AM65_CPSW_STATN_IET_TX_HOLD 0x150 ++#define AM65_CPSW_STATN_IET_TX_FRAG 0x154 ++ ++/* number of priority queues per port FIFO */ ++#define AM65_CPSW_PN_FIFO_PRIO_NUM 8 + + #endif /* AM65_CPSW_QOS_H_ */ +diff -Naur --no-dereference a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c +--- a/drivers/net/ethernet/ti/cpsw.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/cpsw.c 2024-03-28 11:26:09.901017460 -0400 +@@ -631,6 +631,8 @@ + } + } + ++ phy->mac_managed_pm = true; ++ + slave->phy = phy; + + phy_attached_info(slave->phy); +@@ -1722,14 +1724,20 @@ + return ret; + } + +-static int cpsw_remove(struct platform_device *pdev) ++static void cpsw_remove(struct platform_device *pdev) + { + struct cpsw_common *cpsw = platform_get_drvdata(pdev); + int i, ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); +- if (ret < 0) +- return ret; ++ if (ret < 0) { ++ /* Note, if this error path is taken, we're leaking some ++ * resources. ++ */ ++ dev_err(&pdev->dev, "Failed to resume device (%pe)\n", ++ ERR_PTR(ret)); ++ return; ++ } + + for (i = 0; i < cpsw->data.slaves; i++) + if (cpsw->slaves[i].ndev) +@@ -1740,7 +1748,6 @@ + cpsw_remove_dt(pdev); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); +- return 0; + } + + #ifdef CONFIG_PM_SLEEP +@@ -1795,7 +1802,7 @@ + .of_match_table = cpsw_of_mtable, + }, + .probe = cpsw_probe, +- .remove = cpsw_remove, ++ .remove_new = cpsw_remove, + }; + + module_platform_driver(cpsw_driver); +diff -Naur --no-dereference a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c +--- a/drivers/net/ethernet/ti/cpsw_new.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/cpsw_new.c 2024-03-28 11:26:09.901017460 -0400 +@@ -773,6 +773,9 @@ + slave->slave_num); + return; + } ++ ++ phy->mac_managed_pm = true; ++ + slave->phy = phy; + + phy_attached_info(slave->phy); +@@ -2037,14 +2040,20 @@ + return ret; + } + +-static int cpsw_remove(struct platform_device *pdev) ++static void cpsw_remove(struct platform_device *pdev) + { + struct cpsw_common *cpsw = platform_get_drvdata(pdev); + int ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); +- if (ret < 0) +- return ret; ++ if (ret < 0) { ++ /* Note, if this error path is taken, we're leaking some ++ * resources. ++ */ ++ dev_err(&pdev->dev, "Failed to resume device (%pe)\n", ++ ERR_PTR(ret)); ++ return; ++ } + + cpsw_unregister_notifiers(cpsw); + cpsw_unregister_devlink(cpsw); +@@ -2055,7 +2064,6 @@ + cpsw_remove_dt(cpsw); + pm_runtime_put_sync(&pdev->dev); + pm_runtime_disable(&pdev->dev); +- return 0; + } + + static int __maybe_unused cpsw_suspend(struct device *dev) +@@ -2116,7 +2124,7 @@ + .of_match_table = cpsw_of_mtable, + }, + .probe = cpsw_probe, +- .remove = cpsw_remove, ++ .remove_new = cpsw_remove, + }; + + module_platform_driver(cpsw_driver); +diff -Naur --no-dereference a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c +--- a/drivers/net/ethernet/ti/davinci_emac.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/davinci_emac.c 2024-03-28 11:26:09.901017460 -0400 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -47,10 +48,7 @@ + #include + #include + #include +-#include +-#include + #include +-#include + #include + #include + +@@ -1726,13 +1724,10 @@ + #endif + }; + +-static const struct of_device_id davinci_emac_of_match[]; +- + static struct emac_platform_data * + davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv) + { + struct device_node *np; +- const struct of_device_id *match; + const struct emac_platform_data *auxdata; + struct emac_platform_data *pdata = NULL; + +@@ -1779,9 +1774,8 @@ + pdata->interrupt_disable = auxdata->interrupt_disable; + } + +- match = of_match_device(davinci_emac_of_match, &pdev->dev); +- if (match && match->data) { +- auxdata = match->data; ++ auxdata = device_get_match_data(&pdev->dev); ++ if (auxdata) { + pdata->version = auxdata->version; + pdata->hw_ram_addr = auxdata->hw_ram_addr; + } +@@ -1934,18 +1928,20 @@ + goto err_free_rxchan; + ndev->irq = rc; + +- rc = davinci_emac_try_get_mac(pdev, res_ctrl ? 0 : 1, priv->mac_addr); +- if (!rc) +- eth_hw_addr_set(ndev, priv->mac_addr); +- ++ /* If the MAC address is not present, read the registers from the SoC */ + if (!is_valid_ether_addr(priv->mac_addr)) { +- /* Use random MAC if still none obtained. */ +- eth_hw_addr_random(ndev); +- memcpy(priv->mac_addr, ndev->dev_addr, ndev->addr_len); +- dev_warn(&pdev->dev, "using random MAC addr: %pM\n", +- priv->mac_addr); ++ rc = davinci_emac_try_get_mac(pdev, res_ctrl ? 0 : 1, priv->mac_addr); ++ if (!rc) ++ eth_hw_addr_set(ndev, priv->mac_addr); ++ ++ if (!is_valid_ether_addr(priv->mac_addr)) { ++ /* Use random MAC if still none obtained. */ ++ eth_hw_addr_random(ndev); ++ memcpy(priv->mac_addr, ndev->dev_addr, ndev->addr_len); ++ dev_warn(&pdev->dev, "using random MAC addr: %pM\n", ++ priv->mac_addr); ++ } + } +- + ndev->netdev_ops = &emac_netdev_ops; + ndev->ethtool_ops = ðtool_ops; + netif_napi_add(ndev, &priv->napi, emac_poll); +diff -Naur --no-dereference a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c +--- a/drivers/net/ethernet/ti/davinci_mdio.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/davinci_mdio.c 2024-03-28 11:26:09.901017460 -0400 +@@ -511,16 +511,12 @@ + }; + + static const struct soc_device_attribute k3_mdio_socinfo[] = { +- { .family = "AM62X", .revision = "SR1.0", .data = &am65_mdio_soc_data }, +- { .family = "AM64X", .revision = "SR1.0", .data = &am65_mdio_soc_data }, +- { .family = "AM64X", .revision = "SR2.0", .data = &am65_mdio_soc_data }, +- { .family = "AM65X", .revision = "SR1.0", .data = &am65_mdio_soc_data }, +- { .family = "AM65X", .revision = "SR2.0", .data = &am65_mdio_soc_data }, +- { .family = "J7200", .revision = "SR1.0", .data = &am65_mdio_soc_data }, +- { .family = "J7200", .revision = "SR2.0", .data = &am65_mdio_soc_data }, +- { .family = "J721E", .revision = "SR1.0", .data = &am65_mdio_soc_data }, +- { .family = "J721E", .revision = "SR2.0", .data = &am65_mdio_soc_data }, +- { .family = "J721S2", .revision = "SR1.0", .data = &am65_mdio_soc_data}, ++ { .family = "AM62X", .data = &am65_mdio_soc_data }, ++ { .family = "AM64X", .data = &am65_mdio_soc_data }, ++ { .family = "AM65X", .data = &am65_mdio_soc_data }, ++ { .family = "J7200", .data = &am65_mdio_soc_data }, ++ { .family = "J721E", .data = &am65_mdio_soc_data }, ++ { .family = "J721S2", .data = &am65_mdio_soc_data }, + { /* sentinel */ }, + }; + +diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c +--- a/drivers/net/ethernet/ti/icssg/icssg_config.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/icssg/icssg_config.c 2024-03-28 11:26:09.901017460 -0400 +@@ -433,6 +433,17 @@ + return ret; + } + ++void icssg_config_half_duplex(struct prueth_emac *emac) ++{ ++ u32 val; ++ ++ if (!emac->half_duplex) ++ return; ++ ++ val = get_random_u32(); ++ writel(val, emac->dram.va + HD_RAND_SEED_OFFSET); ++} ++ + void icssg_config_set_speed(struct prueth_emac *emac) + { + u8 fw_speed; +@@ -453,5 +464,8 @@ + return; + } + ++ if (emac->duplex == DUPLEX_HALF) ++ fw_speed |= FW_LINK_SPEED_HD; ++ + writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET); + } +diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c +--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c 2024-03-28 11:26:09.901017460 -0400 +@@ -19,11 +19,11 @@ + #include + #include + #include +-#include + #include + #include +-#include ++#include + #include ++#include + #include + #include + #include +@@ -1029,6 +1029,8 @@ + * values + */ + if (emac->link) { ++ if (emac->duplex == DUPLEX_HALF) ++ icssg_config_half_duplex(emac); + /* Set the RGMII cfg for gig en and full duplex */ + icssg_update_rgmii_cfg(prueth->miig_rt, emac); + +@@ -1147,9 +1149,13 @@ + return -ENODEV; + } + ++ if (!emac->half_duplex) { ++ dev_dbg(prueth->dev, "half duplex mode is not supported\n"); ++ phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); ++ phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); ++ } ++ + /* remove unsupported modes */ +- phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); +- phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Pause_BIT); + phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT); +@@ -1653,6 +1659,19 @@ + stats->tx_dropped = ndev->stats.tx_dropped; + } + ++static int emac_ndo_get_phys_port_name(struct net_device *ndev, char *name, ++ size_t len) ++{ ++ struct prueth_emac *emac = netdev_priv(ndev); ++ int ret; ++ ++ ret = snprintf(name, len, "p%d", emac->port_id); ++ if (ret >= len) ++ return -EINVAL; ++ ++ return 0; ++} ++ + static const struct net_device_ops emac_netdev_ops = { + .ndo_open = emac_ndo_open, + .ndo_stop = emac_ndo_stop, +@@ -1663,6 +1682,7 @@ + .ndo_set_rx_mode = emac_ndo_set_rx_mode, + .ndo_eth_ioctl = emac_ndo_ioctl, + .ndo_get_stats64 = emac_ndo_get_stats64, ++ .ndo_get_phys_port_name = emac_ndo_get_phys_port_name, + }; + + /* get emac_port corresponding to eth_node name */ +@@ -1928,8 +1948,6 @@ + pru_rproc_put(prueth->pru[slice]); + } + +-static const struct of_device_id prueth_dt_match[]; +- + static int prueth_probe(struct platform_device *pdev) + { + struct device_node *eth_node, *eth_ports_node; +@@ -1938,7 +1956,6 @@ + struct genpool_data_align gp_data = { + .align = SZ_64K, + }; +- const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct device_node *np; + struct prueth *prueth; +@@ -1948,17 +1965,13 @@ + + np = dev->of_node; + +- match = of_match_device(prueth_dt_match, dev); +- if (!match) +- return -ENODEV; +- + prueth = devm_kzalloc(dev, sizeof(*prueth), GFP_KERNEL); + if (!prueth) + return -ENOMEM; + + dev_set_drvdata(dev, prueth); + prueth->pdev = pdev; +- prueth->pdata = *(const struct prueth_pdata *)match->data; ++ prueth->pdata = *(const struct prueth_pdata *)device_get_match_data(dev); + + prueth->dev = dev; + eth_ports_node = of_get_child_by_name(np, "ethernet-ports"); +@@ -2110,6 +2123,10 @@ + eth0_node->name); + goto exit_iep; + } ++ ++ if (of_find_property(eth0_node, "ti,half-duplex-capable", NULL)) ++ prueth->emac[PRUETH_MAC0]->half_duplex = 1; ++ + prueth->emac[PRUETH_MAC0]->iep = prueth->iep0; + } + +@@ -2121,6 +2138,9 @@ + goto netdev_exit; + } + ++ if (of_find_property(eth1_node, "ti,half-duplex-capable", NULL)) ++ prueth->emac[PRUETH_MAC1]->half_duplex = 1; ++ + prueth->emac[PRUETH_MAC1]->iep = prueth->iep0; + } + +@@ -2318,8 +2338,13 @@ + .quirk_10m_link_issue = 1, + }; + ++static const struct prueth_pdata am64x_icssg_pdata = { ++ .fdqring_mode = K3_RINGACC_RING_MODE_RING, ++}; ++ + static const struct of_device_id prueth_dt_match[] = { + { .compatible = "ti,am654-icssg-prueth", .data = &am654_icssg_pdata }, ++ { .compatible = "ti,am642-icssg-prueth", .data = &am64x_icssg_pdata }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, prueth_dt_match); +diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h +--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h 2024-03-28 11:26:09.901017460 -0400 +@@ -145,6 +145,7 @@ + struct icss_iep *iep; + unsigned int rx_ts_enabled : 1; + unsigned int tx_ts_enabled : 1; ++ unsigned int half_duplex : 1; + + /* DMA related */ + struct prueth_tx_chn tx_chns[PRUETH_MAX_TX_QUEUES]; +@@ -271,6 +272,7 @@ + int emac_set_port_state(struct prueth_emac *emac, + enum icssg_port_state_cmd state); + void icssg_config_set_speed(struct prueth_emac *emac); ++void icssg_config_half_duplex(struct prueth_emac *emac); + + /* Buffer queue helpers */ + int icssg_queue_pop(struct prueth *prueth, u8 queue); +diff -Naur --no-dereference a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig +--- a/drivers/net/ethernet/ti/Kconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/Kconfig 2024-03-28 11:26:09.901017460 -0400 +@@ -134,14 +134,16 @@ + protocol, Ethernet Enhanced Scheduled Traffic Operations (CPTS_ESTFn) + and PCIe Subsystem Precision Time Measurement (PTM). + +-config TI_AM65_CPSW_TAS +- bool "Enable TAS offload in AM65 CPSW" ++config TI_AM65_CPSW_QOS ++ bool "Enable QoS offload features in AM65 CPSW" + depends on TI_K3_AM65_CPSW_NUSS && NET_SCH_TAPRIO && TI_K3_AM65_CPTS + help +- Say y here to support Time Aware Shaper(TAS) offload in AM65 CPSW. +- AM65 CPSW hardware supports Enhanced Scheduled Traffic (EST) +- defined in IEEE 802.1Q 2018. The EST scheduler runs on CPTS and the +- TAS/EST schedule is updated in the Fetch RAM memory of the CPSW. ++ This option enables QoS offload features in AM65 CPSW like ++ Time Aware Shaper (TAS) / Enhanced Scheduled Traffic (EST), ++ MQPRIO qdisc offload and Frame-Preemption MAC Merge / Interspersing ++ Express Traffic (IET). ++ The EST scheduler runs on CPTS and the TAS/EST schedule is ++ updated in the Fetch RAM memory of the CPSW. + + config TI_KEYSTONE_NETCP + tristate "TI Keystone NETCP Core Support" +@@ -194,6 +196,7 @@ + select TI_K3_CPPI_DESC_POOL + depends on PRU_REMOTEPROC + depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER ++ depends on PTP_1588_CLOCK_OPTIONAL + help + Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem. + This subsystem is available starting with the AM65 platform. +diff -Naur --no-dereference a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile +--- a/drivers/net/ethernet/ti/Makefile 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/net/ethernet/ti/Makefile 2024-03-28 11:26:09.901017460 -0400 +@@ -27,7 +27,8 @@ + obj-$(CONFIG_TI_K3_CPPI_DESC_POOL) += k3-cppi-desc-pool.o + + obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o +-ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o am65-cpsw-qos.o ++ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o ++ti-am65-cpsw-nuss-$(CONFIG_TI_AM65_CPSW_QOS) += am65-cpsw-qos.o + ti-am65-cpsw-nuss-$(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV) += am65-cpsw-switchdev.o + obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o + +diff -Naur --no-dereference a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c +--- a/drivers/pci/controller/cadence/pci-j721e.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/pci/controller/cadence/pci-j721e.c 2024-03-28 11:26:09.901017460 -0400 +@@ -42,18 +42,16 @@ + }; + + #define J721E_MODE_RC BIT(7) +-#define LANE_COUNT_MASK BIT(8) + #define LANE_COUNT(n) ((n) << 8) + + #define GENERATION_SEL_MASK GENMASK(1, 0) + +-#define MAX_LANES 2 +- + struct j721e_pcie { + struct cdns_pcie *cdns_pcie; + struct clk *refclk; + u32 mode; + u32 num_lanes; ++ u32 max_lanes; + void __iomem *user_cfg_base; + void __iomem *intd_cfg_base; + u32 linkdown_irq_regfield; +@@ -71,6 +69,7 @@ + unsigned int quirk_disable_flr:1; + u32 linkdown_irq_regfield; + unsigned int byte_access_allowed:1; ++ unsigned int max_lanes; + }; + + static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset) +@@ -206,11 +205,15 @@ + { + struct device *dev = pcie->cdns_pcie->dev; + u32 lanes = pcie->num_lanes; ++ u32 mask = BIT(8); + u32 val = 0; + int ret; + ++ if (pcie->max_lanes == 4) ++ mask = GENMASK(9, 8); ++ + val = LANE_COUNT(lanes - 1); +- ret = regmap_update_bits(syscon, offset, LANE_COUNT_MASK, val); ++ ret = regmap_update_bits(syscon, offset, mask, val); + if (ret) + dev_err(dev, "failed to set link count\n"); + +@@ -290,11 +293,13 @@ + .quirk_retrain_flag = true, + .byte_access_allowed = false, + .linkdown_irq_regfield = LINK_DOWN, ++ .max_lanes = 2, + }; + + static const struct j721e_pcie_data j721e_pcie_ep_data = { + .mode = PCI_MODE_EP, + .linkdown_irq_regfield = LINK_DOWN, ++ .max_lanes = 2, + }; + + static const struct j721e_pcie_data j7200_pcie_rc_data = { +@@ -302,23 +307,41 @@ + .quirk_detect_quiet_flag = true, + .linkdown_irq_regfield = J7200_LINK_DOWN, + .byte_access_allowed = true, ++ .max_lanes = 2, + }; + + static const struct j721e_pcie_data j7200_pcie_ep_data = { + .mode = PCI_MODE_EP, + .quirk_detect_quiet_flag = true, + .quirk_disable_flr = true, ++ .max_lanes = 2, + }; + + static const struct j721e_pcie_data am64_pcie_rc_data = { + .mode = PCI_MODE_RC, + .linkdown_irq_regfield = J7200_LINK_DOWN, + .byte_access_allowed = true, ++ .max_lanes = 1, + }; + + static const struct j721e_pcie_data am64_pcie_ep_data = { + .mode = PCI_MODE_EP, + .linkdown_irq_regfield = J7200_LINK_DOWN, ++ .max_lanes = 1, ++}; ++ ++static const struct j721e_pcie_data j784s4_pcie_rc_data = { ++ .mode = PCI_MODE_RC, ++ .quirk_retrain_flag = true, ++ .byte_access_allowed = false, ++ .linkdown_irq_regfield = LINK_DOWN, ++ .max_lanes = 4, ++}; ++ ++static const struct j721e_pcie_data j784s4_pcie_ep_data = { ++ .mode = PCI_MODE_EP, ++ .linkdown_irq_regfield = LINK_DOWN, ++ .max_lanes = 4, + }; + + static const struct of_device_id of_j721e_pcie_match[] = { +@@ -346,6 +369,14 @@ + .compatible = "ti,am64-pcie-ep", + .data = &am64_pcie_ep_data, + }, ++ { ++ .compatible = "ti,j784s4-pcie-host", ++ .data = &j784s4_pcie_rc_data, ++ }, ++ { ++ .compatible = "ti,j784s4-pcie-ep", ++ .data = &j784s4_pcie_ep_data, ++ }, + {}, + }; + +@@ -432,9 +463,13 @@ + pcie->user_cfg_base = base; + + ret = of_property_read_u32(node, "num-lanes", &num_lanes); +- if (ret || num_lanes > MAX_LANES) ++ if (ret || num_lanes > data->max_lanes) { ++ dev_warn(dev, "num-lanes property not provided or invalid, setting num-lanes to 1\n"); + num_lanes = 1; ++ } ++ + pcie->num_lanes = num_lanes; ++ pcie->max_lanes = data->max_lanes; + + if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48))) + return -EINVAL; +diff -Naur --no-dereference a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c +--- a/drivers/phy/ti/phy-gmii-sel.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/phy/ti/phy-gmii-sel.c 2024-03-28 11:26:09.901017460 -0400 +@@ -248,7 +248,7 @@ + struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = { + .use_of_data = true, + .regfields = phy_gmii_sel_fields_am654, +- .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | ++ .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) | + BIT(PHY_INTERFACE_MODE_USXGMII), + .num_ports = 8, + .num_qsgmii_main_ports = 2, +@@ -494,11 +494,35 @@ + return 0; + } + ++static int phy_gmii_sel_resume_noirq(struct device *dev) ++{ ++ struct phy_gmii_sel_priv *priv = dev_get_drvdata(dev); ++ struct phy_gmii_sel_phy_priv *if_phys = priv->if_phys; ++ int ret, i; ++ ++ for (i = 0; i < priv->num_ports; i++) { ++ if (if_phys[i].phy_if_mode) { ++ ret = phy_gmii_sel_mode(if_phys[i].if_phy, ++ PHY_MODE_ETHERNET, if_phys[i].phy_if_mode); ++ if (ret) { ++ dev_err(dev, "port%u: restore mode fail %d\n", ++ if_phys[i].if_phy->id, ret); ++ return ret; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static DEFINE_NOIRQ_DEV_PM_OPS(phy_gmii_sel_pm_ops, NULL, phy_gmii_sel_resume_noirq); ++ + static struct platform_driver phy_gmii_sel_driver = { + .probe = phy_gmii_sel_probe, + .driver = { + .name = "phy-gmii-sel", + .of_match_table = phy_gmii_sel_id_table, ++ .pm = pm_sleep_ptr(&phy_gmii_sel_pm_ops), + }, + }; + module_platform_driver(phy_gmii_sel_driver); +diff -Naur --no-dereference a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c +--- a/drivers/phy/ti/phy-j721e-wiz.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/phy/ti/phy-j721e-wiz.c 2024-03-28 11:26:09.901017460 -0400 +@@ -1240,6 +1240,7 @@ + case J721E_WIZ_10G: + case J7200_WIZ_10G: + case J721S2_WIZ_10G: ++ case J784S4_WIZ_10G: + if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII) + return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2); + break; +diff -Naur --no-dereference a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c +--- a/drivers/pinctrl/pinctrl-single.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/pinctrl/pinctrl-single.c 2024-03-28 11:26:09.901017460 -0400 +@@ -1960,6 +1960,10 @@ + .irq_status_mask = (1 << 30), /* WKUP_EVT */ + }; + ++static const struct pcs_soc_data pinctrl_single_j7200 = { ++ .flags = PCS_CONTEXT_LOSS_OFF, ++}; ++ + static const struct pcs_soc_data pinctrl_single = { + }; + +@@ -1974,6 +1978,7 @@ + { .compatible = "ti,omap3-padconf", .data = &pinctrl_single_omap_wkup }, + { .compatible = "ti,omap4-padconf", .data = &pinctrl_single_omap_wkup }, + { .compatible = "ti,omap5-padconf", .data = &pinctrl_single_omap_wkup }, ++ { .compatible = "ti,j7200-padconf", .data = &pinctrl_single_j7200 }, + { .compatible = "pinctrl-single", .data = &pinctrl_single }, + { .compatible = "pinconf-single", .data = &pinconf_single }, + { }, +diff -Naur --no-dereference a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c +--- a/drivers/power/supply/bq27xxx_battery.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/power/supply/bq27xxx_battery.c 2024-03-28 11:26:09.901017460 -0400 +@@ -1595,17 +1595,24 @@ + * Return the Design Capacity in µAh + * Or < 0 if something fails. + */ +-static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di) ++static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di, ++ union power_supply_propval *val) + { + int dcap; + ++ /* We only have to read charge design full once */ ++ if (di->charge_design_full > 0) { ++ val->intval = di->charge_design_full; ++ return 0; ++ } ++ + if (di->opts & BQ27XXX_O_ZERO) + dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, true); + else + dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false); + + if (dcap < 0) { +- dev_dbg(di->dev, "error reading initial last measured discharge\n"); ++ dev_dbg(di->dev, "error reading design capacity\n"); + return dcap; + } + +@@ -1614,7 +1621,12 @@ + else + dcap *= 1000; + +- return dcap; ++ /* Save for later reads */ ++ di->charge_design_full = dcap; ++ ++ val->intval = dcap; ++ ++ return 0; + } + + /* +@@ -1865,10 +1877,6 @@ + */ + if (!(di->opts & BQ27XXX_O_ZERO)) + bq27xxx_battery_current_and_status(di, NULL, &status, &cache); +- +- /* We only have to read charge design full once */ +- if (di->charge_design_full <= 0) +- di->charge_design_full = bq27xxx_battery_read_dcap(di); + } + + if ((di->cache.capacity != cache.capacity) || +@@ -2062,7 +2070,7 @@ + ret = bq27xxx_simple_value(di->cache.charge_full, val); + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: +- ret = bq27xxx_simple_value(di->charge_design_full, val); ++ ret = bq27xxx_battery_read_dcap(di, val); + break; + /* + * TODO: Implement these to make registers set from +@@ -2101,6 +2109,13 @@ + mod_delayed_work(system_wq, &di->work, HZ / 2); + } + ++static void bq27xxx_battery_mutex_destroy(void *data) ++{ ++ struct mutex *lock = data; ++ ++ mutex_destroy(lock); ++} ++ + int bq27xxx_battery_setup(struct bq27xxx_device_info *di) + { + struct power_supply_desc *psy_desc; +@@ -2108,9 +2123,14 @@ + .of_node = di->dev->of_node, + .drv_data = di, + }; ++ int ret; + + INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll); + mutex_init(&di->lock); ++ ret = devm_add_action_or_reset(di->dev, bq27xxx_battery_mutex_destroy, ++ &di->lock); ++ if (ret) ++ return ret; + + di->regs = bq27xxx_chip_data[di->chip].regs; + di->unseal_key = bq27xxx_chip_data[di->chip].unseal_key; +@@ -2128,7 +2148,7 @@ + psy_desc->get_property = bq27xxx_battery_get_property; + psy_desc->external_power_changed = bq27xxx_external_power_changed; + +- di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg); ++ di->bat = devm_power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg); + if (IS_ERR(di->bat)) + return dev_err_probe(di->dev, PTR_ERR(di->bat), + "failed to register battery\n"); +@@ -2156,9 +2176,6 @@ + mutex_unlock(&di->lock); + + cancel_delayed_work_sync(&di->work); +- +- power_supply_unregister(di->bat); +- mutex_destroy(&di->lock); + } + EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); + +diff -Naur --no-dereference a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c +--- a/drivers/power/supply/bq27xxx_battery_i2c.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/power/supply/bq27xxx_battery_i2c.c 2024-03-28 11:26:09.901017460 -0400 +@@ -13,8 +13,7 @@ + + #include + +-static DEFINE_IDR(battery_id); +-static DEFINE_MUTEX(battery_mutex); ++static DEFINE_IDA(battery_id); + + static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data) + { +@@ -136,30 +135,39 @@ + return 0; + } + ++static void bq27xxx_battery_i2c_devm_ida_free(void *data) ++{ ++ int num = (long)data; ++ ++ ida_free(&battery_id, num); ++} ++ + static int bq27xxx_battery_i2c_probe(struct i2c_client *client) + { + const struct i2c_device_id *id = i2c_client_get_device_id(client); + struct bq27xxx_device_info *di; + int ret; + char *name; +- int num; ++ long num; + + /* Get new ID for the new battery device */ +- mutex_lock(&battery_mutex); +- num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL); +- mutex_unlock(&battery_mutex); ++ num = ida_alloc(&battery_id, GFP_KERNEL); + if (num < 0) + return num; ++ ret = devm_add_action_or_reset(&client->dev, ++ bq27xxx_battery_i2c_devm_ida_free, ++ (void *)num); ++ if (ret) ++ return ret; + +- name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num); ++ name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%ld", id->name, num); + if (!name) +- goto err_mem; ++ return -ENOMEM; + + di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); + if (!di) +- goto err_mem; ++ return -ENOMEM; + +- di->id = num; + di->dev = &client->dev; + di->chip = id->driver_data; + di->name = name; +@@ -171,7 +179,7 @@ + + ret = bq27xxx_battery_setup(di); + if (ret) +- goto err_failed; ++ return ret; + + /* Schedule a polling after about 1 min */ + schedule_delayed_work(&di->work, 60 * HZ); +@@ -188,21 +196,11 @@ + "Unable to register IRQ %d error %d\n", + client->irq, ret); + bq27xxx_battery_teardown(di); +- goto err_failed; ++ return ret; + } + } + + return 0; +- +-err_mem: +- ret = -ENOMEM; +- +-err_failed: +- mutex_lock(&battery_mutex); +- idr_remove(&battery_id, num); +- mutex_unlock(&battery_mutex); +- +- return ret; + } + + static void bq27xxx_battery_i2c_remove(struct i2c_client *client) +@@ -211,10 +209,6 @@ + + free_irq(client->irq, di); + bq27xxx_battery_teardown(di); +- +- mutex_lock(&battery_mutex); +- idr_remove(&battery_id, di->id); +- mutex_unlock(&battery_mutex); + } + + static const struct i2c_device_id bq27xxx_i2c_id_table[] = { +diff -Naur --no-dereference a/drivers/remoteproc/ti_k3_dsp_remoteproc.c b/drivers/remoteproc/ti_k3_dsp_remoteproc.c +--- a/drivers/remoteproc/ti_k3_dsp_remoteproc.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/remoteproc/ti_k3_dsp_remoteproc.c 2024-03-28 11:26:09.901017460 -0400 +@@ -158,8 +158,8 @@ + /* send the index of the triggered virtqueue in the mailbox payload */ + ret = mbox_send_message(kproc->mbox, (void *)msg); + if (ret < 0) +- dev_err(dev, "failed to send mailbox message, status = %d\n", +- ret); ++ dev_err(dev, "failed to send mailbox message (%pe)\n", ++ ERR_PTR(ret)); + } + + /* Put the DSP processor into reset */ +@@ -170,7 +170,7 @@ + + ret = reset_control_assert(kproc->reset); + if (ret) { +- dev_err(dev, "local-reset assert failed, ret = %d\n", ret); ++ dev_err(dev, "local-reset assert failed (%pe)\n", ERR_PTR(ret)); + return ret; + } + +@@ -180,7 +180,7 @@ + ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, + kproc->ti_sci_id); + if (ret) { +- dev_err(dev, "module-reset assert failed, ret = %d\n", ret); ++ dev_err(dev, "module-reset assert failed (%pe)\n", ERR_PTR(ret)); + if (reset_control_deassert(kproc->reset)) + dev_warn(dev, "local-reset deassert back failed\n"); + } +@@ -200,14 +200,14 @@ + ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci, + kproc->ti_sci_id); + if (ret) { +- dev_err(dev, "module-reset deassert failed, ret = %d\n", ret); ++ dev_err(dev, "module-reset deassert failed (%pe)\n", ERR_PTR(ret)); + return ret; + } + + lreset: + ret = reset_control_deassert(kproc->reset); + if (ret) { +- dev_err(dev, "local-reset deassert failed, ret = %d\n", ret); ++ dev_err(dev, "local-reset deassert failed, (%pe)\n", ERR_PTR(ret)); + if (kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, + kproc->ti_sci_id)) + dev_warn(dev, "module-reset assert back failed\n"); +@@ -246,7 +246,7 @@ + */ + ret = mbox_send_message(kproc->mbox, (void *)RP_MBOX_ECHO_REQUEST); + if (ret < 0) { +- dev_err(dev, "mbox_send_message failed: %d\n", ret); ++ dev_err(dev, "mbox_send_message failed (%pe)\n", ERR_PTR(ret)); + mbox_free_channel(kproc->mbox); + return ret; + } +@@ -272,8 +272,8 @@ + ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci, + kproc->ti_sci_id); + if (ret) +- dev_err(dev, "module-reset deassert failed, cannot enable internal RAM loading, ret = %d\n", +- ret); ++ dev_err(dev, "module-reset deassert failed, cannot enable internal RAM loading (%pe)\n", ++ ERR_PTR(ret)); + + return ret; + } +@@ -296,7 +296,7 @@ + ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci, + kproc->ti_sci_id); + if (ret) +- dev_err(dev, "module-reset assert failed, ret = %d\n", ret); ++ dev_err(dev, "module-reset assert failed (%pe)\n", ERR_PTR(ret)); + + return ret; + } +@@ -550,6 +550,13 @@ + return 0; + } + ++static void k3_dsp_mem_release(void *data) ++{ ++ struct device *dev = data; ++ ++ of_reserved_mem_device_release(dev); ++} ++ + static int k3_dsp_reserved_mem_init(struct k3_dsp_rproc *kproc) + { + struct device *dev = kproc->dev; +@@ -561,9 +568,9 @@ + + num_rmems = of_property_count_elems_of_size(np, "memory-region", + sizeof(phandle)); +- if (num_rmems <= 0) { +- dev_err(dev, "device does not reserved memory regions, ret = %d\n", +- num_rmems); ++ if (num_rmems < 0) { ++ dev_err(dev, "device does not reserved memory regions (%pe)\n", ++ ERR_PTR(num_rmems)); + return -EINVAL; + } + if (num_rmems < 2) { +@@ -575,31 +582,29 @@ + /* use reserved memory region 0 for vring DMA allocations */ + ret = of_reserved_mem_device_init_by_idx(dev, np, 0); + if (ret) { +- dev_err(dev, "device cannot initialize DMA pool, ret = %d\n", +- ret); ++ dev_err(dev, "device cannot initialize DMA pool (%pe)\n", ++ ERR_PTR(ret)); + return ret; + } ++ ret = devm_add_action_or_reset(dev, k3_dsp_mem_release, dev); ++ if (ret) ++ return ret; + + num_rmems--; +- kproc->rmem = kcalloc(num_rmems, sizeof(*kproc->rmem), GFP_KERNEL); +- if (!kproc->rmem) { +- ret = -ENOMEM; +- goto release_rmem; +- } ++ kproc->rmem = devm_kcalloc(dev, num_rmems, sizeof(*kproc->rmem), GFP_KERNEL); ++ if (!kproc->rmem) ++ return -ENOMEM; + + /* use remaining reserved memory regions for static carveouts */ + for (i = 0; i < num_rmems; i++) { + rmem_np = of_parse_phandle(np, "memory-region", i + 1); +- if (!rmem_np) { +- ret = -EINVAL; +- goto unmap_rmem; +- } ++ if (!rmem_np) ++ return -EINVAL; + + rmem = of_reserved_mem_lookup(rmem_np); + if (!rmem) { + of_node_put(rmem_np); +- ret = -EINVAL; +- goto unmap_rmem; ++ return -EINVAL; + } + of_node_put(rmem_np); + +@@ -607,12 +612,11 @@ + /* 64-bit address regions currently not supported */ + kproc->rmem[i].dev_addr = (u32)rmem->base; + kproc->rmem[i].size = rmem->size; +- kproc->rmem[i].cpu_addr = ioremap_wc(rmem->base, rmem->size); ++ kproc->rmem[i].cpu_addr = devm_ioremap_wc(dev, rmem->base, rmem->size); + if (!kproc->rmem[i].cpu_addr) { + dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n", + i + 1, &rmem->base, &rmem->size); +- ret = -ENOMEM; +- goto unmap_rmem; ++ return -ENOMEM; + } + + dev_dbg(dev, "reserved memory%d: bus addr %pa size 0x%zx va %pK da 0x%x\n", +@@ -623,25 +627,13 @@ + kproc->num_rmems = num_rmems; + + return 0; +- +-unmap_rmem: +- for (i--; i >= 0; i--) +- iounmap(kproc->rmem[i].cpu_addr); +- kfree(kproc->rmem); +-release_rmem: +- of_reserved_mem_device_release(kproc->dev); +- return ret; + } + +-static void k3_dsp_reserved_mem_exit(struct k3_dsp_rproc *kproc) ++static void k3_dsp_release_tsp(void *data) + { +- int i; ++ struct ti_sci_proc *tsp = data; + +- for (i = 0; i < kproc->num_rmems; i++) +- iounmap(kproc->rmem[i].cpu_addr); +- kfree(kproc->rmem); +- +- of_reserved_mem_device_release(kproc->dev); ++ ti_sci_proc_release(tsp); + } + + static +@@ -657,7 +649,7 @@ + if (ret < 0) + return ERR_PTR(ret); + +- tsp = kzalloc(sizeof(*tsp), GFP_KERNEL); ++ tsp = devm_kzalloc(dev, sizeof(*tsp), GFP_KERNEL); + if (!tsp) + return ERR_PTR(-ENOMEM); + +@@ -680,21 +672,17 @@ + const char *fw_name; + bool p_state = false; + int ret = 0; +- int ret1; + + data = of_device_get_match_data(dev); + if (!data) + return -ENODEV; + + ret = rproc_of_parse_firmware(dev, 0, &fw_name); +- if (ret) { +- dev_err(dev, "failed to parse firmware-name property, ret = %d\n", +- ret); +- return ret; +- } ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to parse firmware-name property\n"); + +- rproc = rproc_alloc(dev, dev_name(dev), &k3_dsp_rproc_ops, fw_name, +- sizeof(*kproc)); ++ rproc = devm_rproc_alloc(dev, dev_name(dev), &k3_dsp_rproc_ops, ++ fw_name, sizeof(*kproc)); + if (!rproc) + return -ENOMEM; + +@@ -709,61 +697,46 @@ + kproc->dev = dev; + kproc->data = data; + +- kproc->ti_sci = ti_sci_get_by_phandle(np, "ti,sci"); +- if (IS_ERR(kproc->ti_sci)) { +- ret = PTR_ERR(kproc->ti_sci); +- if (ret != -EPROBE_DEFER) { +- dev_err(dev, "failed to get ti-sci handle, ret = %d\n", +- ret); +- } +- kproc->ti_sci = NULL; +- goto free_rproc; +- } ++ kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci"); ++ if (IS_ERR(kproc->ti_sci)) ++ return dev_err_probe(dev, PTR_ERR(kproc->ti_sci), ++ "failed to get ti-sci handle\n"); + + ret = of_property_read_u32(np, "ti,sci-dev-id", &kproc->ti_sci_id); +- if (ret) { +- dev_err(dev, "missing 'ti,sci-dev-id' property\n"); +- goto put_sci; +- } ++ if (ret) ++ return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n"); + + kproc->reset = devm_reset_control_get_exclusive(dev, NULL); +- if (IS_ERR(kproc->reset)) { +- ret = PTR_ERR(kproc->reset); +- dev_err(dev, "failed to get reset, status = %d\n", ret); +- goto put_sci; +- } ++ if (IS_ERR(kproc->reset)) ++ return dev_err_probe(dev, PTR_ERR(kproc->reset), ++ "failed to get reset\n"); + + kproc->tsp = k3_dsp_rproc_of_get_tsp(dev, kproc->ti_sci); +- if (IS_ERR(kproc->tsp)) { +- dev_err(dev, "failed to construct ti-sci proc control, ret = %d\n", +- ret); +- ret = PTR_ERR(kproc->tsp); +- goto put_sci; +- } ++ if (IS_ERR(kproc->tsp)) ++ return dev_err_probe(dev, PTR_ERR(kproc->tsp), ++ "failed to construct ti-sci proc control\n"); + + ret = ti_sci_proc_request(kproc->tsp); + if (ret < 0) { +- dev_err(dev, "ti_sci_proc_request failed, ret = %d\n", ret); +- goto free_tsp; ++ dev_err_probe(dev, ret, "ti_sci_proc_request failed\n"); ++ return ret; + } ++ ret = devm_add_action_or_reset(dev, k3_dsp_release_tsp, kproc->tsp); ++ if (ret) ++ return ret; + + ret = k3_dsp_rproc_of_get_memories(pdev, kproc); + if (ret) +- goto release_tsp; ++ return ret; + + ret = k3_dsp_reserved_mem_init(kproc); +- if (ret) { +- dev_err(dev, "reserved memory init failed, ret = %d\n", ret); +- goto release_tsp; +- } ++ if (ret) ++ return dev_err_probe(dev, ret, "reserved memory init failed\n"); + + ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id, + NULL, &p_state); +- if (ret) { +- dev_err(dev, "failed to get initial state, mode cannot be determined, ret = %d\n", +- ret); +- goto release_mem; +- } ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to get initial state, mode cannot be determined\n"); + + /* configure J721E devices for either remoteproc or IPC-only mode */ + if (p_state) { +@@ -787,9 +760,7 @@ + if (data->uses_lreset) { + ret = reset_control_status(kproc->reset); + if (ret < 0) { +- dev_err(dev, "failed to get reset status, status = %d\n", +- ret); +- goto release_mem; ++ return dev_err_probe(dev, ret, "failed to get reset status\n"); + } else if (ret == 0) { + dev_warn(dev, "local reset is deasserted for device\n"); + k3_dsp_rproc_reset(kproc); +@@ -797,35 +768,16 @@ + } + } + +- ret = rproc_add(rproc); +- if (ret) { +- dev_err(dev, "failed to add register device with remoteproc core, status = %d\n", +- ret); +- goto release_mem; +- } ++ ret = devm_rproc_add(dev, rproc); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to add register device with remoteproc core\n"); + + platform_set_drvdata(pdev, kproc); + + return 0; +- +-release_mem: +- k3_dsp_reserved_mem_exit(kproc); +-release_tsp: +- ret1 = ti_sci_proc_release(kproc->tsp); +- if (ret1) +- dev_err(dev, "failed to release proc, ret = %d\n", ret1); +-free_tsp: +- kfree(kproc->tsp); +-put_sci: +- ret1 = ti_sci_put_handle(kproc->ti_sci); +- if (ret1) +- dev_err(dev, "failed to put ti_sci handle, ret = %d\n", ret1); +-free_rproc: +- rproc_free(rproc); +- return ret; + } + +-static int k3_dsp_rproc_remove(struct platform_device *pdev) ++static void k3_dsp_rproc_remove(struct platform_device *pdev) + { + struct k3_dsp_rproc *kproc = platform_get_drvdata(pdev); + struct rproc *rproc = kproc->rproc; +@@ -834,28 +786,9 @@ + + if (rproc->state == RPROC_ATTACHED) { + ret = rproc_detach(rproc); +- if (ret) { +- dev_err(dev, "failed to detach proc, ret = %d\n", ret); +- return ret; +- } ++ if (ret) ++ dev_err(dev, "failed to detach proc (%pe)\n", ERR_PTR(ret)); + } +- +- rproc_del(kproc->rproc); +- +- ret = ti_sci_proc_release(kproc->tsp); +- if (ret) +- dev_err(dev, "failed to release proc, ret = %d\n", ret); +- +- kfree(kproc->tsp); +- +- ret = ti_sci_put_handle(kproc->ti_sci); +- if (ret) +- dev_err(dev, "failed to put ti_sci handle, ret = %d\n", ret); +- +- k3_dsp_reserved_mem_exit(kproc); +- rproc_free(kproc->rproc); +- +- return 0; + } + + static const struct k3_dsp_mem_data c66_mems[] = { +@@ -906,7 +839,7 @@ + + static struct platform_driver k3_dsp_rproc_driver = { + .probe = k3_dsp_rproc_probe, +- .remove = k3_dsp_rproc_remove, ++ .remove_new = k3_dsp_rproc_remove, + .driver = { + .name = "k3-dsp-rproc", + .of_match_table = k3_dsp_of_match, +diff -Naur --no-dereference a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c +--- a/drivers/soc/ti/k3-socinfo.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/soc/ti/k3-socinfo.c 2024-03-28 11:26:09.901017460 -0400 +@@ -20,7 +20,7 @@ + * 31-28 VARIANT Device variant + * 27-12 PARTNO Part number + * 11-1 MFG Indicates TI as manufacturer (0x17) +- * 1 Always 1 ++ * 0 Always 1 + */ + #define CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT (28) + #define CTRLMMR_WKUP_JTAGID_VARIANT_MASK GENMASK(31, 28) +@@ -33,19 +33,35 @@ + + #define CTRLMMR_WKUP_JTAGID_MFG_TI 0x17 + ++#define JTAG_ID_PARTNO_AM65X 0xBB5A ++#define JTAG_ID_PARTNO_J721E 0xBB64 ++#define JTAG_ID_PARTNO_J7200 0xBB6D ++#define JTAG_ID_PARTNO_AM64X 0xBB38 ++#define JTAG_ID_PARTNO_J721S2 0xBB75 ++#define JTAG_ID_PARTNO_AM62X 0xBB7E ++#define JTAG_ID_PARTNO_J784S4 0xBB80 ++#define JTAG_ID_PARTNO_AM62AX 0xBB8D ++#define JTAG_ID_PARTNO_AM62PX 0xBB9D ++#define JTAG_ID_PARTNO_J722S 0xBBA0 ++ + static const struct k3_soc_id { + unsigned int id; + const char *family_name; + } k3_soc_ids[] = { +- { 0xBB5A, "AM65X" }, +- { 0xBB64, "J721E" }, +- { 0xBB6D, "J7200" }, +- { 0xBB38, "AM64X" }, +- { 0xBB75, "J721S2"}, +- { 0xBB7E, "AM62X" }, +- { 0xBB80, "J784S4" }, +- { 0xBB8D, "AM62AX" }, +- { 0xBB9D, "AM62PX" }, ++ { JTAG_ID_PARTNO_AM65X, "AM65X" }, ++ { JTAG_ID_PARTNO_J721E, "J721E" }, ++ { JTAG_ID_PARTNO_J7200, "J7200" }, ++ { JTAG_ID_PARTNO_AM64X, "AM64X" }, ++ { JTAG_ID_PARTNO_J721S2, "J721S2"}, ++ { JTAG_ID_PARTNO_AM62X, "AM62X" }, ++ { JTAG_ID_PARTNO_J784S4, "J784S4" }, ++ { JTAG_ID_PARTNO_AM62AX, "AM62AX" }, ++ { JTAG_ID_PARTNO_AM62PX, "AM62PX" }, ++ { JTAG_ID_PARTNO_J722S, "J722S" }, ++}; ++ ++static const char * const j721e_rev_string_map[] = { ++ "1.0", "1.1", + }; + + static int +@@ -60,7 +76,33 @@ + return 0; + } + +- return -EINVAL; ++ return -ENODEV; ++} ++ ++static int ++k3_chipinfo_variant_to_sr(unsigned int partno, unsigned int variant, ++ struct soc_device_attribute *soc_dev_attr) ++{ ++ switch (partno) { ++ case JTAG_ID_PARTNO_J721E: ++ if (variant >= ARRAY_SIZE(j721e_rev_string_map)) ++ goto err_unknown_variant; ++ soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s", ++ j721e_rev_string_map[variant]); ++ break; ++ default: ++ variant++; ++ soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0", ++ variant); ++ } ++ ++ if (!soc_dev_attr->revision) ++ return -ENOMEM; ++ ++ return 0; ++ ++err_unknown_variant: ++ return -ENODEV; + } + + static int k3_chipinfo_probe(struct platform_device *pdev) +@@ -94,7 +136,6 @@ + + variant = (jtag_id & CTRLMMR_WKUP_JTAGID_VARIANT_MASK) >> + CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT; +- variant++; + + partno_id = (jtag_id & CTRLMMR_WKUP_JTAGID_PARTNO_MASK) >> + CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT; +@@ -103,17 +144,16 @@ + if (!soc_dev_attr) + return -ENOMEM; + +- soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0", variant); +- if (!soc_dev_attr->revision) { +- ret = -ENOMEM; ++ ret = k3_chipinfo_partno_to_names(partno_id, soc_dev_attr); ++ if (ret) { ++ dev_err(dev, "Unknown SoC JTAGID[0x%08X]: %d\n", jtag_id, ret); + goto err; + } + +- ret = k3_chipinfo_partno_to_names(partno_id, soc_dev_attr); ++ ret = k3_chipinfo_variant_to_sr(partno_id, variant, soc_dev_attr); + if (ret) { +- dev_err(dev, "Unknown SoC JTAGID[0x%08X]\n", jtag_id); +- ret = -ENODEV; +- goto err_free_rev; ++ dev_err(dev, "Unknown SoC SR[0x%08X]: %d\n", jtag_id, ret); ++ goto err; + } + + node = of_find_node_by_path("/"); +diff -Naur --no-dereference a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c +--- a/drivers/spi/spi-cadence-quadspi.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/spi/spi-cadence-quadspi.c 2024-03-28 11:26:09.901017460 -0400 +@@ -116,6 +116,9 @@ + #define CQSPI_TIMEOUT_MS 500 + #define CQSPI_READ_TIMEOUT_MS 10 + ++/* Runtime_pm autosuspend delay */ ++#define CQSPI_AUTOSUSPEND_TIMEOUT 2000 ++ + #define CQSPI_DUMMY_CLKS_PER_BYTE 8 + #define CQSPI_DUMMY_BYTES_MAX 4 + #define CQSPI_DUMMY_CLKS_MAX 31 +@@ -1407,8 +1410,20 @@ + static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) + { + int ret; ++ struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master); ++ struct device *dev = &cqspi->pdev->dev; ++ ++ ret = pm_runtime_resume_and_get(dev); ++ if (ret) { ++ dev_err(&mem->spi->dev, "resume failed with %d\n", ret); ++ return ret; ++ } + + ret = cqspi_mem_process(mem, op); ++ ++ pm_runtime_mark_last_busy(dev); ++ pm_runtime_put_autosuspend(dev); ++ + if (ret) + dev_err(&mem->spi->dev, "operation failed with %d\n", ret); + +@@ -1753,10 +1768,10 @@ + if (irq < 0) + return -ENXIO; + +- pm_runtime_enable(dev); +- ret = pm_runtime_resume_and_get(dev); +- if (ret < 0) +- goto probe_pm_failed; ++ ret = pm_runtime_set_active(dev); ++ if (ret) ++ return ret; ++ + + ret = clk_prepare_enable(cqspi->clk); + if (ret) { +@@ -1862,12 +1877,26 @@ + goto probe_setup_failed; + } + ++ ret = devm_pm_runtime_enable(dev); ++ if (ret) { ++ if (cqspi->rx_chan) ++ dma_release_channel(cqspi->rx_chan); ++ goto probe_setup_failed; ++ } ++ ++ pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT); ++ pm_runtime_use_autosuspend(dev); ++ pm_runtime_get_noresume(dev); ++ + ret = spi_register_controller(host); + if (ret) { + dev_err(&pdev->dev, "failed to register SPI ctlr %d\n", ret); + goto probe_setup_failed; + } + ++ pm_runtime_mark_last_busy(dev); ++ pm_runtime_put_autosuspend(dev); ++ + return 0; + probe_setup_failed: + cqspi_controller_enable(cqspi, 0); +@@ -1876,9 +1905,6 @@ + cqspi_jh7110_disable_clk(pdev, cqspi); + clk_disable_unprepare(cqspi->clk); + probe_clk_failed: +- pm_runtime_put_sync(dev); +-probe_pm_failed: +- pm_runtime_disable(dev); + return ret; + } + +@@ -1930,7 +1956,8 @@ + return spi_controller_resume(host); + } + +-static DEFINE_SIMPLE_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, cqspi_resume); ++static DEFINE_RUNTIME_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, ++ cqspi_resume, NULL); + + static const struct cqspi_driver_platdata cdns_qspi = { + .quirks = CQSPI_DISABLE_DAC_MODE, +@@ -2014,7 +2041,7 @@ + .remove_new = cqspi_remove, + .driver = { + .name = CQSPI_NAME, +- .pm = &cqspi_dev_pm_ops, ++ .pm = pm_ptr(&cqspi_dev_pm_ops), + .of_match_table = cqspi_dt_ids, + }, + }; +diff -Naur --no-dereference a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c +--- a/drivers/uio/uio_pdrv_genirq.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/uio/uio_pdrv_genirq.c 2024-03-28 11:26:09.901017460 -0400 +@@ -276,11 +276,13 @@ + + #ifdef CONFIG_OF + static struct of_device_id uio_of_genirq_match[] = { ++ { .compatible = "uio" }, ++ { .compatible = "ti,pruss-shmem" }, + { /* This is filled with module_parm */ }, + { /* Sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, uio_of_genirq_match); +-module_param_string(of_id, uio_of_genirq_match[0].compatible, 128, 0); ++module_param_string(of_id, uio_of_genirq_match[2].compatible, 128, 0); + MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio"); + #endif + +diff -Naur --no-dereference a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c +--- a/drivers/uio/uio_pruss.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/uio/uio_pruss.c 2024-03-28 11:26:09.901017460 -0400 +@@ -1,4 +1,3 @@ +-// SPDX-License-Identifier: GPL-2.0-only + /* + * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss) + * +@@ -6,6 +5,15 @@ + * and DDR RAM to user space for applications interacting with PRUSS firmware + * + * Copyright (C) 2010-11 Texas Instruments Incorporated - http://www.ti.com/ ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. + */ + #include + #include +@@ -18,14 +26,22 @@ + #include + #include + #include ++#include ++#ifdef CONFIG_ARCH_DAVINCI_DA850 + #include ++#else ++#include ++#endif + + #define DRV_NAME "pruss_uio" + #define DRV_VERSION "1.0" + ++#ifdef CONFIG_ARCH_DAVINCI_DA850 + static int sram_pool_sz = SZ_16K; + module_param(sram_pool_sz, int, 0); +-MODULE_PARM_DESC(sram_pool_sz, "sram pool size to allocate "); ++MODULE_PARM_DESC(sram_pool_sz, "sram pool size to allocate"); ++#endif ++ + + static int extram_pool_sz = SZ_256K; + module_param(extram_pool_sz, int, 0); +@@ -53,22 +69,23 @@ + #define PINTC_HIER 0x1500 + + struct uio_pruss_dev { +- struct uio_info *info; +- struct clk *pruss_clk; +- dma_addr_t sram_paddr; ++ struct uio_info info[MAX_PRUSS_EVT]; + dma_addr_t ddr_paddr; + void __iomem *prussio_vaddr; +- unsigned long sram_vaddr; + void *ddr_vaddr; +- unsigned int hostirq_start; + unsigned int pintc_base; ++#ifdef CONFIG_ARCH_DAVINCI_DA850 ++ struct clk *pruss_clk; + struct gen_pool *sram_pool; ++ dma_addr_t sram_paddr; ++ unsigned long sram_vaddr; ++#endif + }; + + static irqreturn_t pruss_handler(int irq, struct uio_info *info) + { + struct uio_pruss_dev *gdev = info->priv; +- int intr_bit = (irq - gdev->hostirq_start + 2); ++ int intr_bit = 2 + (info - gdev->info); + int val, intr_mask = (1 << intr_bit); + void __iomem *base = gdev->prussio_vaddr + gdev->pintc_base; + void __iomem *intren_reg = base + PINTC_HIER; +@@ -86,53 +103,66 @@ + + static void pruss_cleanup(struct device *dev, struct uio_pruss_dev *gdev) + { +- int cnt; +- struct uio_info *p = gdev->info; ++ int i; + +- for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) { +- uio_unregister_device(p); ++ for (i = 0; i < MAX_PRUSS_EVT; i++) { ++ uio_unregister_device(&gdev->info[i]); ++ kfree(gdev->info[i].name); + } + iounmap(gdev->prussio_vaddr); + if (gdev->ddr_vaddr) { + dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr, + gdev->ddr_paddr); + } ++#ifdef CONFIG_ARCH_DAVINCI_DA850 + if (gdev->sram_vaddr) + gen_pool_free(gdev->sram_pool, + gdev->sram_vaddr, + sram_pool_sz); + clk_disable(gdev->pruss_clk); ++ clk_put(gdev->pruss_clk); ++#else ++ pm_runtime_put(dev); ++ pm_runtime_disable(dev); ++#endif ++ kfree(gdev); + } + + static int pruss_probe(struct platform_device *pdev) + { +- struct uio_info *p; + struct uio_pruss_dev *gdev; + struct resource *regs_prussio; + struct device *dev = &pdev->dev; +- int ret, cnt, i, len; ++ int ret, i, len; + struct uio_pruss_pdata *pdata = dev_get_platdata(dev); + +- gdev = devm_kzalloc(dev, sizeof(struct uio_pruss_dev), GFP_KERNEL); ++ gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL); + if (!gdev) + return -ENOMEM; + +- gdev->info = devm_kcalloc(dev, MAX_PRUSS_EVT, sizeof(*p), GFP_KERNEL); +- if (!gdev->info) +- return -ENOMEM; +- ++#ifdef CONFIG_ARCH_DAVINCI_DA850 + /* Power on PRU in case its not done as part of boot-loader */ +- gdev->pruss_clk = devm_clk_get(dev, "pruss"); ++ gdev->pruss_clk = clk_get(dev, "pruss"); + if (IS_ERR(gdev->pruss_clk)) { + dev_err(dev, "Failed to get clock\n"); +- return PTR_ERR(gdev->pruss_clk); ++ ret = PTR_ERR(gdev->pruss_clk); ++ goto err_free_gdev; + } + + ret = clk_enable(gdev->pruss_clk); + if (ret) { + dev_err(dev, "Failed to enable clock\n"); +- return ret; ++ goto err_clk_put; ++ } ++#else ++ pm_runtime_enable(dev); ++ ret = pm_runtime_get_sync(dev); ++ if (ret < 0) { ++ dev_err(dev, "pm_runtime_get_sync() failed\n"); ++ pm_runtime_disable(dev); ++ goto err_free_gdev; + } ++#endif + + regs_prussio = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs_prussio) { +@@ -147,6 +177,18 @@ + goto err_clk_disable; + } + ++ if (dev->of_node) { ++ ret = of_property_read_u32(dev->of_node, ++ "ti,pintc-offset", ++ &gdev->pintc_base); ++ if (ret < 0) { ++ dev_err(dev, "Can't parse ti,pintc-offset property\n"); ++ goto err_clk_disable; ++ } ++ } else ++ gdev->pintc_base = pdata->pintc_base; ++ ++#ifdef CONFIG_ARCH_DAVINCI_DA850 + if (pdata->sram_pool) { + gdev->sram_pool = pdata->sram_pool; + gdev->sram_vaddr = +@@ -158,9 +200,10 @@ + goto err_clk_disable; + } + } ++#endif + + gdev->ddr_vaddr = dma_alloc_coherent(dev, extram_pool_sz, +- &(gdev->ddr_paddr), GFP_KERNEL | GFP_DMA); ++ &gdev->ddr_paddr, GFP_KERNEL | GFP_DMA); + if (!gdev->ddr_vaddr) { + dev_err(dev, "Could not allocate external memory\n"); + ret = -ENOMEM; +@@ -170,61 +213,85 @@ + len = resource_size(regs_prussio); + gdev->prussio_vaddr = ioremap(regs_prussio->start, len); + if (!gdev->prussio_vaddr) { +- dev_err(dev, "Can't remap PRUSS I/O address range\n"); ++ dev_err(dev, "Can't remap PRUSS I/O address range\n"); + ret = -ENOMEM; + goto err_free_ddr_vaddr; + } + +- ret = platform_get_irq(pdev, 0); +- if (ret < 0) +- goto err_unmap; ++ for (i = 0; i < MAX_PRUSS_EVT; i++) { ++ struct uio_info *p = &gdev->info[i]; + +- gdev->hostirq_start = ret; +- gdev->pintc_base = pdata->pintc_base; +- +- for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) { ++ p->mem[0].name = "pruss"; + p->mem[0].addr = regs_prussio->start; + p->mem[0].size = resource_size(regs_prussio); + p->mem[0].memtype = UIO_MEM_PHYS; + ++ /* note: some userspace code uses hardcoded mem indices... */ ++#ifdef CONFIG_ARCH_DAVINCI_DA850 ++ p->mem[1].name = "sram"; + p->mem[1].addr = gdev->sram_paddr; + p->mem[1].size = sram_pool_sz; + p->mem[1].memtype = UIO_MEM_PHYS; + ++ p->mem[2].name = "ddr"; + p->mem[2].addr = gdev->ddr_paddr; + p->mem[2].size = extram_pool_sz; + p->mem[2].memtype = UIO_MEM_PHYS; ++#else ++ p->mem[1].name = "ddr"; ++ p->mem[1].addr = gdev->ddr_paddr; ++ p->mem[1].size = extram_pool_sz; ++ p->mem[1].memtype = UIO_MEM_PHYS; ++#endif ++ ++ ret = platform_get_irq(pdev, i); ++ if (ret < 0) { ++ dev_err(dev, "Failed to obtain irq %d (%d)\n", i, ret); ++ goto err_unloop; ++ } + +- p->name = devm_kasprintf(dev, GFP_KERNEL, "pruss_evt%d", cnt); ++ p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", i); + p->version = DRV_VERSION; + + /* Register PRUSS IRQ lines */ +- p->irq = gdev->hostirq_start + cnt; ++ p->irq = ret; + p->handler = pruss_handler; + p->priv = gdev; + + ret = uio_register_device(dev, p); +- if (ret < 0) ++ if (ret < 0) { ++ kfree(p->name); + goto err_unloop; ++ } + } + + platform_set_drvdata(pdev, gdev); + return 0; + + err_unloop: +- for (i = 0, p = gdev->info; i < cnt; i++, p++) { +- uio_unregister_device(p); ++ while( --i >= 0 ) { ++ uio_unregister_device(&gdev->info[i]); ++ kfree(gdev->info[i].name); + } +-err_unmap: + iounmap(gdev->prussio_vaddr); + err_free_ddr_vaddr: + dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr, + gdev->ddr_paddr); + err_free_sram: ++#ifdef CONFIG_ARCH_DAVINCI_DA850 + if (pdata->sram_pool) + gen_pool_free(gdev->sram_pool, gdev->sram_vaddr, sram_pool_sz); + err_clk_disable: + clk_disable(gdev->pruss_clk); ++err_clk_put: ++ clk_put(gdev->pruss_clk); ++#else ++err_clk_disable: ++ pm_runtime_put(dev); ++ pm_runtime_disable(dev); ++#endif ++err_free_gdev: ++ kfree(gdev); + + return ret; + } +@@ -237,11 +304,19 @@ + return 0; + } + ++static const struct of_device_id pruss_dt_ids[] = { ++ { .compatible = "ti,pruss-v1" }, ++ { .compatible = "ti,pruss-v2" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, pruss_dt_ids); ++ + static struct platform_driver pruss_driver = { + .probe = pruss_probe, + .remove = pruss_remove, + .driver = { + .name = DRV_NAME, ++ .of_match_table = pruss_dt_ids, + }, + }; + +diff -Naur --no-dereference a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c +--- a/drivers/usb/typec/tipd/core.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/usb/typec/tipd/core.c 2024-03-28 11:26:09.901017460 -0400 +@@ -8,6 +8,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -17,6 +18,7 @@ + #include + #include + #include ++#include + + #include "tps6598x.h" + #include "trace.h" +@@ -36,13 +38,36 @@ + #define TPS_REG_STATUS 0x1a + #define TPS_REG_SYSTEM_CONF 0x28 + #define TPS_REG_CTRL_CONF 0x29 ++#define TPS_REG_BOOT_STATUS 0x2D + #define TPS_REG_POWER_STATUS 0x3f ++#define TPS_REG_PD_STATUS 0x40 + #define TPS_REG_RX_IDENTITY_SOP 0x48 + #define TPS_REG_DATA_STATUS 0x5f ++#define TPS_REG_SLEEP_CONF 0x70 + + /* TPS_REG_SYSTEM_CONF bits */ + #define TPS_SYSCONF_PORTINFO(c) ((c) & 7) + ++/* ++ * BPMs task timeout, recommended 5 seconds ++ * pg.48 TPS2575 Host Interface Technical Reference ++ * Manual (Rev. A) ++ * https://www.ti.com/lit/ug/slvuc05a/slvuc05a.pdf ++ */ ++#define TPS_BUNDLE_TIMEOUT 0x32 ++ ++/* BPMs return code */ ++#define TPS_TASK_BPMS_INVALID_BUNDLE_SIZE 0x4 ++#define TPS_TASK_BPMS_INVALID_SLAVE_ADDR 0x5 ++#define TPS_TASK_BPMS_INVALID_TIMEOUT 0x6 ++ ++/* PBMc data out */ ++#define TPS_PBMC_RC 0 /* Return code */ ++#define TPS_PBMC_DPCS 2 /* device patch complete status */ ++ ++/* reset de-assertion to ready for operation */ ++#define TPS_SETUP_MS 1000 ++ + enum { + TPS_PORTINFO_SINK, + TPS_PORTINFO_SINK_ACCESSORY, +@@ -68,6 +93,7 @@ + TPS_MODE_BOOT, + TPS_MODE_BIST, + TPS_MODE_DISC, ++ TPS_MODE_PTCH, + }; + + static const char *const modes[] = { +@@ -75,17 +101,31 @@ + [TPS_MODE_BOOT] = "BOOT", + [TPS_MODE_BIST] = "BIST", + [TPS_MODE_DISC] = "DISC", ++ [TPS_MODE_PTCH] = "PTCH", + }; + + /* Unrecognized commands will be replaced with "!CMD" */ + #define INVALID_CMD(_cmd_) (_cmd_ == 0x444d4321) + ++struct tps6598x; ++ ++struct tipd_data { ++ irq_handler_t irq_handler; ++ int (*register_port)(struct tps6598x *tps, struct fwnode_handle *node); ++ void (*trace_power_status)(u16 status); ++ void (*trace_status)(u32 status); ++ int (*apply_patch)(struct tps6598x *tps); ++ int (*init)(struct tps6598x *tps); ++ int (*reset)(struct tps6598x *tps); ++}; ++ + struct tps6598x { + struct device *dev; + struct regmap *regmap; + struct mutex lock; /* device lock */ + u8 i2c_protocol:1; + ++ struct gpio_desc *reset; + struct typec_port *port; + struct typec_partner *partner; + struct usb_pd_identity partner_identity; +@@ -97,9 +137,11 @@ + enum power_supply_usb_type usb_type; + + int wakeup; ++ u32 status; /* status reg */ + u16 pwr_status; + struct delayed_work wq_poll; +- irq_handler_t irq_handler; ++ ++ const struct tipd_data *data; + }; + + static enum power_supply_property tps6598x_psy_props[] = { +@@ -180,6 +222,11 @@ + return tps6598x_block_read(tps, reg, val, sizeof(u64)); + } + ++static inline int tps6598x_write8(struct tps6598x *tps, u8 reg, u8 val) ++{ ++ return tps6598x_block_write(tps, reg, &val, sizeof(u8)); ++} ++ + static inline int tps6598x_write64(struct tps6598x *tps, u8 reg, u64 val) + { + return tps6598x_block_write(tps, reg, &val, sizeof(u64)); +@@ -282,9 +329,10 @@ + power_supply_changed(tps->psy); + } + +-static int tps6598x_exec_cmd(struct tps6598x *tps, const char *cmd, +- size_t in_len, u8 *in_data, +- size_t out_len, u8 *out_data) ++static int tps6598x_exec_cmd_tmo(struct tps6598x *tps, const char *cmd, ++ size_t in_len, const u8 *in_data, ++ size_t out_len, u8 *out_data, ++ u32 cmd_timeout_ms, u32 res_delay_ms) + { + unsigned long timeout; + u32 val; +@@ -307,8 +355,7 @@ + if (ret < 0) + return ret; + +- /* XXX: Using 1s for now, but it may not be enough for every command. */ +- timeout = jiffies + msecs_to_jiffies(1000); ++ timeout = jiffies + msecs_to_jiffies(cmd_timeout_ms); + + do { + ret = tps6598x_read32(tps, TPS_REG_CMD1, &val); +@@ -321,6 +368,9 @@ + return -ETIMEDOUT; + } while (val); + ++ /* some commands require delay for the result to be available */ ++ mdelay(res_delay_ms); ++ + if (out_len) { + ret = tps6598x_block_read(tps, TPS_REG_DATA1, + out_data, out_len); +@@ -345,6 +395,14 @@ + return 0; + } + ++static int tps6598x_exec_cmd(struct tps6598x *tps, const char *cmd, ++ size_t in_len, const u8 *in_data, ++ size_t out_len, u8 *out_data) ++{ ++ return tps6598x_exec_cmd_tmo(tps, cmd, in_len, in_data, ++ out_len, out_data, 1000, 0); ++} ++ + static int tps6598x_dr_set(struct typec_port *port, enum typec_data_role role) + { + const char *cmd = (role == TYPEC_DEVICE) ? "SWUF" : "SWDF"; +@@ -419,7 +477,9 @@ + dev_err(tps->dev, "%s: failed to read status\n", __func__); + return false; + } +- trace_tps6598x_status(*status); ++ ++ if (tps->data->trace_status) ++ tps->data->trace_status(*status); + + return true; + } +@@ -450,7 +510,9 @@ + return false; + } + tps->pwr_status = pwr_status; +- trace_tps6598x_power_status(pwr_status); ++ ++ if (tps->data->trace_power_status) ++ tps->data->trace_power_status(pwr_status); + + return true; + } +@@ -513,6 +575,65 @@ + return IRQ_NONE; + } + ++static bool tps6598x_has_role_changed(struct tps6598x *tps, u32 status) ++{ ++ status ^= tps->status; ++ ++ return status & (TPS_STATUS_PORTROLE | TPS_STATUS_DATAROLE); ++} ++ ++static irqreturn_t tps25750_interrupt(int irq, void *data) ++{ ++ struct tps6598x *tps = data; ++ u64 event[2] = { }; ++ u32 status; ++ int ret; ++ ++ mutex_lock(&tps->lock); ++ ++ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT1, event, 11); ++ if (ret) { ++ dev_err(tps->dev, "%s: failed to read events\n", __func__); ++ goto err_unlock; ++ } ++ trace_tps25750_irq(event[0]); ++ ++ if (!(event[0] | event[1])) ++ goto err_unlock; ++ ++ if (!tps6598x_read_status(tps, &status)) ++ goto err_clear_ints; ++ ++ if ((event[0] | event[1]) & TPS_REG_INT_POWER_STATUS_UPDATE) ++ if (!tps6598x_read_power_status(tps)) ++ goto err_clear_ints; ++ ++ if ((event[0] | event[1]) & TPS_REG_INT_DATA_STATUS_UPDATE) ++ if (!tps6598x_read_data_status(tps)) ++ goto err_clear_ints; ++ ++ /* ++ * data/port roles could be updated independently after ++ * a plug event. Therefore, we need to check ++ * for pr/dr status change to set TypeC dr/pr accordingly. ++ */ ++ if ((event[0] | event[1]) & TPS_REG_INT_PLUG_EVENT || ++ tps6598x_has_role_changed(tps, status)) ++ tps6598x_handle_plug_event(tps, status); ++ ++ tps->status = status; ++ ++err_clear_ints: ++ tps6598x_block_write(tps, TPS_REG_INT_CLEAR1, event, 11); ++ ++err_unlock: ++ mutex_unlock(&tps->lock); ++ ++ if (event[0] | event[1]) ++ return IRQ_HANDLED; ++ return IRQ_NONE; ++} ++ + static irqreturn_t tps6598x_interrupt(int irq, void *data) + { + struct tps6598x *tps = data; +@@ -568,7 +689,7 @@ + struct tps6598x *tps = container_of(to_delayed_work(work), + struct tps6598x, wq_poll); + +- tps->irq_handler(0, tps); ++ tps->data->irq_handler(0, tps); + queue_delayed_work(system_power_efficient_wq, + &tps->wq_poll, msecs_to_jiffies(POLL_INTERVAL)); + } +@@ -582,12 +703,15 @@ + if (ret) + return ret; + +- switch (match_string(modes, ARRAY_SIZE(modes), mode)) { ++ ret = match_string(modes, ARRAY_SIZE(modes), mode); ++ ++ switch (ret) { + case TPS_MODE_APP: +- return 0; ++ case TPS_MODE_PTCH: ++ return ret; + case TPS_MODE_BOOT: + dev_warn(tps->dev, "dead-battery condition\n"); +- return 0; ++ return ret; + case TPS_MODE_BIST: + case TPS_MODE_DISC: + default: +@@ -697,15 +821,478 @@ + return PTR_ERR_OR_ZERO(tps->psy); + } + ++static int ++tps6598x_register_port(struct tps6598x *tps, struct fwnode_handle *fwnode) ++{ ++ int ret; ++ u32 conf; ++ struct typec_capability typec_cap = { }; ++ ++ ret = tps6598x_read32(tps, TPS_REG_SYSTEM_CONF, &conf); ++ if (ret) ++ return ret; ++ ++ typec_cap.revision = USB_TYPEC_REV_1_2; ++ typec_cap.pd_revision = 0x200; ++ typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE; ++ typec_cap.driver_data = tps; ++ typec_cap.ops = &tps6598x_ops; ++ typec_cap.fwnode = fwnode; ++ ++ switch (TPS_SYSCONF_PORTINFO(conf)) { ++ case TPS_PORTINFO_SINK_ACCESSORY: ++ case TPS_PORTINFO_SINK: ++ typec_cap.type = TYPEC_PORT_SNK; ++ typec_cap.data = TYPEC_PORT_UFP; ++ break; ++ case TPS_PORTINFO_DRP_UFP_DRD: ++ case TPS_PORTINFO_DRP_DFP_DRD: ++ typec_cap.type = TYPEC_PORT_DRP; ++ typec_cap.data = TYPEC_PORT_DRD; ++ break; ++ case TPS_PORTINFO_DRP_UFP: ++ typec_cap.type = TYPEC_PORT_DRP; ++ typec_cap.data = TYPEC_PORT_UFP; ++ break; ++ case TPS_PORTINFO_DRP_DFP: ++ typec_cap.type = TYPEC_PORT_DRP; ++ typec_cap.data = TYPEC_PORT_DFP; ++ break; ++ case TPS_PORTINFO_SOURCE: ++ typec_cap.type = TYPEC_PORT_SRC; ++ typec_cap.data = TYPEC_PORT_DFP; ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ tps->port = typec_register_port(tps->dev, &typec_cap); ++ if (IS_ERR(tps->port)) ++ return PTR_ERR(tps->port); ++ ++ return 0; ++} ++ ++static int tps_request_firmware(struct tps6598x *tps, const struct firmware **fw) ++{ ++ const char *firmware_name; ++ int ret; ++ ++ ret = device_property_read_string(tps->dev, "firmware-name", ++ &firmware_name); ++ if (ret) ++ return ret; ++ ++ ret = request_firmware(fw, firmware_name, tps->dev); ++ if (ret) { ++ dev_err(tps->dev, "failed to retrieve \"%s\"\n", firmware_name); ++ return ret; ++ } ++ ++ if ((*fw)->size == 0) { ++ release_firmware(*fw); ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static int ++tps25750_write_firmware(struct tps6598x *tps, ++ u8 bpms_addr, const u8 *data, size_t len) ++{ ++ struct i2c_client *client = to_i2c_client(tps->dev); ++ int ret; ++ u8 slave_addr; ++ int timeout; ++ ++ slave_addr = client->addr; ++ timeout = client->adapter->timeout; ++ ++ /* ++ * binary configuration size is around ~16Kbytes ++ * which might take some time to finish writing it ++ */ ++ client->adapter->timeout = msecs_to_jiffies(5000); ++ client->addr = bpms_addr; ++ ++ ret = regmap_raw_write(tps->regmap, data[0], &data[1], len - 1); ++ ++ client->addr = slave_addr; ++ client->adapter->timeout = timeout; ++ ++ return ret; ++} ++ ++static int ++tps25750_exec_pbms(struct tps6598x *tps, u8 *in_data, size_t in_len) ++{ ++ int ret; ++ u8 rc; ++ ++ ret = tps6598x_exec_cmd_tmo(tps, "PBMs", in_len, in_data, ++ sizeof(rc), &rc, 4000, 0); ++ if (ret) ++ return ret; ++ ++ switch (rc) { ++ case TPS_TASK_BPMS_INVALID_BUNDLE_SIZE: ++ dev_err(tps->dev, "%s: invalid fw size\n", __func__); ++ return -EINVAL; ++ case TPS_TASK_BPMS_INVALID_SLAVE_ADDR: ++ dev_err(tps->dev, "%s: invalid slave address\n", __func__); ++ return -EINVAL; ++ case TPS_TASK_BPMS_INVALID_TIMEOUT: ++ dev_err(tps->dev, "%s: timed out\n", __func__); ++ return -ETIMEDOUT; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int tps25750_abort_patch_process(struct tps6598x *tps) ++{ ++ int ret; ++ ++ ret = tps6598x_exec_cmd(tps, "PBMe", 0, NULL, 0, NULL); ++ if (ret) ++ return ret; ++ ++ ret = tps6598x_check_mode(tps); ++ if (ret != TPS_MODE_PTCH) ++ dev_err(tps->dev, "failed to switch to \"PTCH\" mode\n"); ++ ++ return ret; ++} ++ ++static int tps25750_start_patch_burst_mode(struct tps6598x *tps) ++{ ++ int ret; ++ const struct firmware *fw; ++ const char *firmware_name; ++ struct { ++ u32 fw_size; ++ u8 addr; ++ u8 timeout; ++ } __packed bpms_data; ++ u32 addr; ++ struct device_node *np = tps->dev->of_node; ++ ++ ret = device_property_read_string(tps->dev, "firmware-name", ++ &firmware_name); ++ if (ret) ++ return ret; ++ ++ ret = tps_request_firmware(tps, &fw); ++ if (ret) ++ return ret; ++ ++ ret = of_property_match_string(np, "reg-names", "patch-address"); ++ if (ret < 0) { ++ dev_err(tps->dev, "failed to get patch-address %d\n", ret); ++ goto release_fw; ++ } ++ ++ ret = of_property_read_u32_index(np, "reg", ret, &addr); ++ if (ret) ++ goto release_fw; ++ ++ if (addr == 0 || (addr >= 0x20 && addr <= 0x23)) { ++ dev_err(tps->dev, "wrong patch address %u\n", addr); ++ ret = -EINVAL; ++ goto release_fw; ++ } ++ ++ bpms_data.addr = (u8)addr; ++ bpms_data.fw_size = fw->size; ++ bpms_data.timeout = TPS_BUNDLE_TIMEOUT; ++ ++ ret = tps25750_exec_pbms(tps, (u8 *)&bpms_data, sizeof(bpms_data)); ++ if (ret) ++ goto release_fw; ++ ++ ret = tps25750_write_firmware(tps, bpms_data.addr, fw->data, fw->size); ++ if (ret) { ++ dev_err(tps->dev, "Failed to write patch %s of %zu bytes\n", ++ firmware_name, fw->size); ++ goto release_fw; ++ } ++ ++ /* ++ * A delay of 500us is required after the firmware is written ++ * based on pg.62 in tps6598x Host Interface Technical ++ * Reference Manual ++ * https://www.ti.com/lit/ug/slvuc05a/slvuc05a.pdf ++ */ ++ udelay(500); ++ ++release_fw: ++ release_firmware(fw); ++ ++ return ret; ++} ++ ++static int tps25750_complete_patch_process(struct tps6598x *tps) ++{ ++ int ret; ++ u8 out_data[40]; ++ u8 dummy[2] = { }; ++ ++ /* ++ * Without writing something to DATA_IN, this command would ++ * return an error ++ */ ++ ret = tps6598x_exec_cmd_tmo(tps, "PBMc", sizeof(dummy), dummy, ++ sizeof(out_data), out_data, 2000, 20); ++ if (ret) ++ return ret; ++ ++ if (out_data[TPS_PBMC_RC]) { ++ dev_err(tps->dev, ++ "%s: pbmc failed: %u\n", __func__, ++ out_data[TPS_PBMC_RC]); ++ return -EIO; ++ } ++ ++ if (out_data[TPS_PBMC_DPCS]) { ++ dev_err(tps->dev, ++ "%s: failed device patch complete status: %u\n", ++ __func__, out_data[TPS_PBMC_DPCS]); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int tps25750_apply_patch(struct tps6598x *tps) ++{ ++ int ret; ++ unsigned long timeout; ++ u64 status = 0; ++ ++ ret = tps6598x_block_read(tps, TPS_REG_BOOT_STATUS, &status, 5); ++ if (ret) ++ return ret; ++ /* ++ * Nothing to be done if the configuration ++ * is being loaded from EERPOM ++ */ ++ if (status & TPS_BOOT_STATUS_I2C_EEPROM_PRESENT) ++ goto wait_for_app; ++ ++ ret = tps25750_start_patch_burst_mode(tps); ++ if (ret) { ++ tps25750_abort_patch_process(tps); ++ return ret; ++ } ++ ++ ret = tps25750_complete_patch_process(tps); ++ if (ret) ++ return ret; ++ ++wait_for_app: ++ timeout = jiffies + msecs_to_jiffies(1000); ++ ++ do { ++ ret = tps6598x_check_mode(tps); ++ if (ret < 0) ++ return ret; ++ ++ if (time_is_before_jiffies(timeout)) ++ return -ETIMEDOUT; ++ ++ } while (ret != TPS_MODE_APP); ++ ++ /* ++ * The dead battery flag may be triggered when the controller ++ * port is connected to a device that can source power and ++ * attempts to power up both the controller and the board it is on. ++ * To restore controller functionality, it is necessary to clear ++ * this flag ++ */ ++ if (status & TPS_BOOT_STATUS_DEAD_BATTERY_FLAG) { ++ ret = tps6598x_exec_cmd(tps, "DBfg", 0, NULL, 0, NULL); ++ if (ret) { ++ dev_err(tps->dev, "failed to clear dead battery %d\n", ret); ++ return ret; ++ } ++ } ++ ++ dev_info(tps->dev, "controller switched to \"APP\" mode\n"); ++ ++ return 0; ++}; ++ ++static int tps6598x_apply_patch(struct tps6598x *tps) ++{ ++ u8 in = TPS_PTCS_CONTENT_DEV | TPS_PTCS_CONTENT_APP; ++ u8 out[TPS_MAX_LEN] = {0}; ++ size_t in_len = sizeof(in); ++ size_t copied_bytes = 0; ++ size_t bytes_left; ++ const struct firmware *fw; ++ const char *firmware_name; ++ int ret; ++ ++ ret = device_property_read_string(tps->dev, "firmware-name", ++ &firmware_name); ++ if (ret) ++ return ret; ++ ++ ret = tps_request_firmware(tps, &fw); ++ if (ret) ++ return ret; ++ ++ ret = tps6598x_exec_cmd(tps, "PTCs", in_len, &in, ++ TPS_PTCS_OUT_BYTES, out); ++ if (ret || out[TPS_PTCS_STATUS] == TPS_PTCS_STATUS_FAIL) { ++ if (!ret) ++ ret = -EBUSY; ++ dev_err(tps->dev, "Update start failed (%d)\n", ret); ++ goto release_fw; ++ } ++ ++ bytes_left = fw->size; ++ while (bytes_left) { ++ if (bytes_left < TPS_MAX_LEN) ++ in_len = bytes_left; ++ else ++ in_len = TPS_MAX_LEN; ++ ret = tps6598x_exec_cmd(tps, "PTCd", in_len, ++ fw->data + copied_bytes, ++ TPS_PTCD_OUT_BYTES, out); ++ if (ret || out[TPS_PTCD_TRANSFER_STATUS] || ++ out[TPS_PTCD_LOADING_STATE] == TPS_PTCD_LOAD_ERR) { ++ if (!ret) ++ ret = -EBUSY; ++ dev_err(tps->dev, "Patch download failed (%d)\n", ret); ++ goto release_fw; ++ } ++ copied_bytes += in_len; ++ bytes_left -= in_len; ++ } ++ ++ ret = tps6598x_exec_cmd(tps, "PTCc", 0, NULL, TPS_PTCC_OUT_BYTES, out); ++ if (ret || out[TPS_PTCC_DEV] || out[TPS_PTCC_APP]) { ++ if (!ret) ++ ret = -EBUSY; ++ dev_err(tps->dev, "Update completion failed (%d)\n", ret); ++ goto release_fw; ++ } ++ msleep(TPS_SETUP_MS); ++ dev_info(tps->dev, "Firmware update succeeded\n"); ++ ++release_fw: ++ release_firmware(fw); ++ ++ return ret; ++}; ++ ++static int cd321x_init(struct tps6598x *tps) ++{ ++ return 0; ++} ++ ++static int tps25750_init(struct tps6598x *tps) ++{ ++ int ret; ++ ++ ret = tps->data->apply_patch(tps); ++ if (ret) ++ return ret; ++ ++ ret = tps6598x_write8(tps, TPS_REG_SLEEP_CONF, ++ TPS_SLEEP_CONF_SLEEP_MODE_ALLOWED); ++ if (ret) ++ dev_warn(tps->dev, ++ "%s: failed to enable sleep mode: %d\n", ++ __func__, ret); ++ ++ return 0; ++} ++ ++static int tps6598x_init(struct tps6598x *tps) ++{ ++ return tps->data->apply_patch(tps); ++} ++ ++static int cd321x_reset(struct tps6598x *tps) ++{ ++ return 0; ++} ++ ++static int tps25750_reset(struct tps6598x *tps) ++{ ++ return tps6598x_exec_cmd_tmo(tps, "GAID", 0, NULL, 0, NULL, 2000, 0); ++} ++ ++static int tps6598x_reset(struct tps6598x *tps) ++{ ++ return 0; ++} ++ ++static int ++tps25750_register_port(struct tps6598x *tps, struct fwnode_handle *fwnode) ++{ ++ struct typec_capability typec_cap = { }; ++ const char *data_role; ++ u8 pd_status; ++ int ret; ++ ++ ret = tps6598x_read8(tps, TPS_REG_PD_STATUS, &pd_status); ++ if (ret) ++ return ret; ++ ++ ret = fwnode_property_read_string(fwnode, "data-role", &data_role); ++ if (ret) { ++ dev_err(tps->dev, "data-role not found: %d\n", ret); ++ return ret; ++ } ++ ++ ret = typec_find_port_data_role(data_role); ++ if (ret < 0) { ++ dev_err(tps->dev, "unknown data-role: %s\n", data_role); ++ return ret; ++ } ++ ++ typec_cap.data = ret; ++ typec_cap.revision = USB_TYPEC_REV_1_3; ++ typec_cap.pd_revision = 0x300; ++ typec_cap.driver_data = tps; ++ typec_cap.ops = &tps6598x_ops; ++ typec_cap.fwnode = fwnode; ++ typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE; ++ ++ switch (TPS_PD_STATUS_PORT_TYPE(pd_status)) { ++ case TPS_PD_STATUS_PORT_TYPE_SINK_SOURCE: ++ case TPS_PD_STATUS_PORT_TYPE_SOURCE_SINK: ++ typec_cap.type = TYPEC_PORT_DRP; ++ break; ++ case TPS_PD_STATUS_PORT_TYPE_SINK: ++ typec_cap.type = TYPEC_PORT_SNK; ++ break; ++ case TPS_PD_STATUS_PORT_TYPE_SOURCE: ++ typec_cap.type = TYPEC_PORT_SRC; ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ tps->port = typec_register_port(tps->dev, &typec_cap); ++ if (IS_ERR(tps->port)) ++ return PTR_ERR(tps->port); ++ ++ return 0; ++} ++ + static int tps6598x_probe(struct i2c_client *client) + { +- irq_handler_t irq_handler = tps6598x_interrupt; + struct device_node *np = client->dev.of_node; +- struct typec_capability typec_cap = { }; + struct tps6598x *tps; + struct fwnode_handle *fwnode; + u32 status; +- u32 conf; + u32 vid; + int ret; + u64 mask1; +@@ -717,13 +1304,22 @@ + mutex_init(&tps->lock); + tps->dev = &client->dev; + ++ tps->reset = devm_gpiod_get_optional(tps->dev, "reset", GPIOD_OUT_LOW); ++ if (IS_ERR(tps->reset)) ++ return dev_err_probe(tps->dev, PTR_ERR(tps->reset), ++ "failed to get reset GPIO\n"); ++ if (tps->reset) ++ msleep(TPS_SETUP_MS); ++ + tps->regmap = devm_regmap_init_i2c(client, &tps6598x_regmap_config); + if (IS_ERR(tps->regmap)) + return PTR_ERR(tps->regmap); + +- ret = tps6598x_read32(tps, TPS_REG_VID, &vid); +- if (ret < 0 || !vid) +- return -ENODEV; ++ if (!device_is_compatible(tps->dev, "ti,tps25750")) { ++ ret = tps6598x_read32(tps, TPS_REG_VID, &vid); ++ if (ret < 0 || !vid) ++ return -ENODEV; ++ } + + /* + * Checking can the adapter handle SMBus protocol. If it can not, the +@@ -743,7 +1339,6 @@ + APPLE_CD_REG_INT_DATA_STATUS_UPDATE | + APPLE_CD_REG_INT_PLUG_EVENT; + +- irq_handler = cd321x_interrupt; + } else { + /* Enable power status, data status and plug event interrupts */ + mask1 = TPS_REG_INT_POWER_STATUS_UPDATE | +@@ -751,24 +1346,32 @@ + TPS_REG_INT_PLUG_EVENT; + } + +- tps->irq_handler = irq_handler; ++ if (dev_fwnode(tps->dev)) ++ tps->data = device_get_match_data(tps->dev); ++ else ++ tps->data = i2c_get_match_data(client); ++ if (!tps->data) ++ return -EINVAL; ++ + /* Make sure the controller has application firmware running */ + ret = tps6598x_check_mode(tps); +- if (ret) ++ if (ret < 0) + return ret; + ++ if (ret == TPS_MODE_PTCH) { ++ ret = tps->data->init(tps); ++ if (ret) ++ return ret; ++ } ++ + ret = tps6598x_write64(tps, TPS_REG_INT_MASK1, mask1); + if (ret) +- return ret; ++ goto err_reset_controller; + +- ret = tps6598x_read32(tps, TPS_REG_STATUS, &status); +- if (ret < 0) +- goto err_clear_mask; +- trace_tps6598x_status(status); +- +- ret = tps6598x_read32(tps, TPS_REG_SYSTEM_CONF, &conf); +- if (ret < 0) ++ if (!tps6598x_read_status(tps, &status)) { ++ ret = -ENODEV; + goto err_clear_mask; ++ } + + /* + * This fwnode has a "compatible" property, but is never populated as a +@@ -787,50 +1390,13 @@ + goto err_fwnode_put; + } + +- typec_cap.revision = USB_TYPEC_REV_1_2; +- typec_cap.pd_revision = 0x200; +- typec_cap.prefer_role = TYPEC_NO_PREFERRED_ROLE; +- typec_cap.driver_data = tps; +- typec_cap.ops = &tps6598x_ops; +- typec_cap.fwnode = fwnode; +- +- switch (TPS_SYSCONF_PORTINFO(conf)) { +- case TPS_PORTINFO_SINK_ACCESSORY: +- case TPS_PORTINFO_SINK: +- typec_cap.type = TYPEC_PORT_SNK; +- typec_cap.data = TYPEC_PORT_UFP; +- break; +- case TPS_PORTINFO_DRP_UFP_DRD: +- case TPS_PORTINFO_DRP_DFP_DRD: +- typec_cap.type = TYPEC_PORT_DRP; +- typec_cap.data = TYPEC_PORT_DRD; +- break; +- case TPS_PORTINFO_DRP_UFP: +- typec_cap.type = TYPEC_PORT_DRP; +- typec_cap.data = TYPEC_PORT_UFP; +- break; +- case TPS_PORTINFO_DRP_DFP: +- typec_cap.type = TYPEC_PORT_DRP; +- typec_cap.data = TYPEC_PORT_DFP; +- break; +- case TPS_PORTINFO_SOURCE: +- typec_cap.type = TYPEC_PORT_SRC; +- typec_cap.data = TYPEC_PORT_DFP; +- break; +- default: +- ret = -ENODEV; +- goto err_role_put; +- } +- + ret = devm_tps6598_psy_register(tps); + if (ret) + goto err_role_put; + +- tps->port = typec_register_port(&client->dev, &typec_cap); +- if (IS_ERR(tps->port)) { +- ret = PTR_ERR(tps->port); ++ ret = tps->data->register_port(tps, fwnode); ++ if (ret) + goto err_role_put; +- } + + if (status & TPS_STATUS_PLUG_PRESENT) { + ret = tps6598x_read16(tps, TPS_REG_POWER_STATUS, &tps->pwr_status); +@@ -845,7 +1411,7 @@ + + if (client->irq) { + ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, +- irq_handler, ++ tps->data->irq_handler, + IRQF_SHARED | IRQF_ONESHOT, + dev_name(&client->dev), tps); + } else { +@@ -879,6 +1445,10 @@ + fwnode_handle_put(fwnode); + err_clear_mask: + tps6598x_write64(tps, TPS_REG_INT_MASK1, 0); ++err_reset_controller: ++ /* Reset PD controller to remove any applied patch */ ++ tps->data->reset(tps); ++ + return ret; + } + +@@ -889,9 +1459,16 @@ + if (!client->irq) + cancel_delayed_work_sync(&tps->wq_poll); + ++ devm_free_irq(tps->dev, client->irq, tps); + tps6598x_disconnect(tps, 0); + typec_unregister_port(tps->port); + usb_role_switch_put(tps->role_sw); ++ ++ /* Reset PD controller to remove any applied patch */ ++ tps->data->reset(tps); ++ ++ if (tps->reset) ++ gpiod_set_value_cansleep(tps->reset, 1); + } + + static int __maybe_unused tps6598x_suspend(struct device *dev) +@@ -902,6 +1479,8 @@ + if (tps->wakeup) { + disable_irq(client->irq); + enable_irq_wake(client->irq); ++ } else if (tps->reset) { ++ gpiod_set_value_cansleep(tps->reset, 1); + } + + if (!client->irq) +@@ -914,10 +1493,24 @@ + { + struct i2c_client *client = to_i2c_client(dev); + struct tps6598x *tps = i2c_get_clientdata(client); ++ int ret; ++ ++ ret = tps6598x_check_mode(tps); ++ if (ret < 0) ++ return ret; ++ ++ if (ret == TPS_MODE_PTCH) { ++ ret = tps->data->init(tps); ++ if (ret) ++ return ret; ++ } + + if (tps->wakeup) { + disable_irq_wake(client->irq); + enable_irq(client->irq); ++ } else if (tps->reset) { ++ gpiod_set_value_cansleep(tps->reset, 0); ++ msleep(TPS_SETUP_MS); + } + + if (!client->irq) +@@ -931,15 +1524,45 @@ + SET_SYSTEM_SLEEP_PM_OPS(tps6598x_suspend, tps6598x_resume) + }; + ++static const struct tipd_data cd321x_data = { ++ .irq_handler = cd321x_interrupt, ++ .register_port = tps6598x_register_port, ++ .trace_power_status = trace_tps6598x_power_status, ++ .trace_status = trace_tps6598x_status, ++ .init = cd321x_init, ++ .reset = cd321x_reset, ++}; ++ ++static const struct tipd_data tps6598x_data = { ++ .irq_handler = tps6598x_interrupt, ++ .register_port = tps6598x_register_port, ++ .trace_power_status = trace_tps6598x_power_status, ++ .trace_status = trace_tps6598x_status, ++ .apply_patch = tps6598x_apply_patch, ++ .init = tps6598x_init, ++ .reset = tps6598x_reset, ++}; ++ ++static const struct tipd_data tps25750_data = { ++ .irq_handler = tps25750_interrupt, ++ .register_port = tps25750_register_port, ++ .trace_power_status = trace_tps25750_power_status, ++ .trace_status = trace_tps25750_status, ++ .apply_patch = tps25750_apply_patch, ++ .init = tps25750_init, ++ .reset = tps25750_reset, ++}; ++ + static const struct of_device_id tps6598x_of_match[] = { +- { .compatible = "ti,tps6598x", }, +- { .compatible = "apple,cd321x", }, ++ { .compatible = "ti,tps6598x", &tps6598x_data}, ++ { .compatible = "apple,cd321x", &cd321x_data}, ++ { .compatible = "ti,tps25750", &tps25750_data}, + {} + }; + MODULE_DEVICE_TABLE(of, tps6598x_of_match); + + static const struct i2c_device_id tps6598x_id[] = { +- { "tps6598x" }, ++ { "tps6598x", (kernel_ulong_t)&tps6598x_data }, + { } + }; + MODULE_DEVICE_TABLE(i2c, tps6598x_id); +diff -Naur --no-dereference a/drivers/usb/typec/tipd/tps6598x.h b/drivers/usb/typec/tipd/tps6598x.h +--- a/drivers/usb/typec/tipd/tps6598x.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/usb/typec/tipd/tps6598x.h 2024-03-28 11:26:09.901017460 -0400 +@@ -161,6 +161,25 @@ + #define TPS_POWER_STATUS_BC12_STATUS_CDP 2 + #define TPS_POWER_STATUS_BC12_STATUS_DCP 3 + ++/* TPS25750_REG_POWER_STATUS bits */ ++#define TPS25750_POWER_STATUS_CHARGER_DETECT_STATUS_MASK GENMASK(7, 4) ++#define TPS25750_POWER_STATUS_CHARGER_DETECT_STATUS(p) \ ++ TPS_FIELD_GET(TPS25750_POWER_STATUS_CHARGER_DETECT_STATUS_MASK, (p)) ++#define TPS25750_POWER_STATUS_CHARGER_ADVERTISE_STATUS_MASK GENMASK(9, 8) ++#define TPS25750_POWER_STATUS_CHARGER_ADVERTISE_STATUS(p) \ ++ TPS_FIELD_GET(TPS25750_POWER_STATUS_CHARGER_ADVERTISE_STATUS_MASK, (p)) ++ ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_DISABLED 0 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_IN_PROGRESS 1 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_NONE 2 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_SPD 3 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_BC_1_2_CPD 4 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_BC_1_2_DPD 5 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_DIV_1_DCP 6 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_DIV_2_DCP 7 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_DIV_3_DCP 8 ++#define TPS25750_POWER_STATUS_CHARGER_DET_STATUS_1_2V_DCP 9 ++ + /* TPS_REG_DATA_STATUS bits */ + #define TPS_DATA_STATUS_DATA_CONNECTION BIT(0) + #define TPS_DATA_STATUS_UPSIDE_DOWN BIT(1) +@@ -199,4 +218,39 @@ + #define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_A BIT(2) + #define TPS_DATA_STATUS_DP_SPEC_PIN_ASSIGNMENT_B (BIT(2) | BIT(1)) + ++/* BOOT STATUS REG*/ ++#define TPS_BOOT_STATUS_DEAD_BATTERY_FLAG BIT(2) ++#define TPS_BOOT_STATUS_I2C_EEPROM_PRESENT BIT(3) ++ ++/* PD STATUS REG */ ++#define TPS_REG_PD_STATUS_PORT_TYPE_MASK GENMASK(5, 4) ++#define TPS_PD_STATUS_PORT_TYPE(x) \ ++ TPS_FIELD_GET(TPS_REG_PD_STATUS_PORT_TYPE_MASK, x) ++ ++#define TPS_PD_STATUS_PORT_TYPE_SINK_SOURCE 0 ++#define TPS_PD_STATUS_PORT_TYPE_SINK 1 ++#define TPS_PD_STATUS_PORT_TYPE_SOURCE 2 ++#define TPS_PD_STATUS_PORT_TYPE_SOURCE_SINK 3 ++ ++/* SLEEP CONF REG */ ++#define TPS_SLEEP_CONF_SLEEP_MODE_ALLOWED BIT(0) ++ ++/* Start Patch Download Sequence */ ++#define TPS_PTCS_CONTENT_APP BIT(0) ++#define TPS_PTCS_CONTENT_DEV BIT(1) ++#define TPS_PTCS_OUT_BYTES 4 ++#define TPS_PTCS_STATUS 1 ++ ++#define TPS_PTCS_STATUS_FAIL 0x80 ++/* Patch Download */ ++#define TPS_PTCD_OUT_BYTES 10 ++#define TPS_PTCD_TRANSFER_STATUS 1 ++#define TPS_PTCD_LOADING_STATE 2 ++ ++#define TPS_PTCD_LOAD_ERR 0x09 ++/* Patch Download Complete */ ++#define TPS_PTCC_OUT_BYTES 4 ++#define TPS_PTCC_DEV 2 ++#define TPS_PTCC_APP 3 ++ + #endif /* __TPS6598X_H__ */ +diff -Naur --no-dereference a/drivers/usb/typec/tipd/trace.h b/drivers/usb/typec/tipd/trace.h +--- a/drivers/usb/typec/tipd/trace.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/usb/typec/tipd/trace.h 2024-03-28 11:26:09.901017460 -0400 +@@ -74,6 +74,13 @@ + { APPLE_CD_REG_INT_DATA_STATUS_UPDATE, "DATA_STATUS_UPDATE" }, \ + { APPLE_CD_REG_INT_STATUS_UPDATE, "STATUS_UPDATE" }) + ++#define show_tps25750_irq_flags(flags) \ ++ __print_flags_u64(flags, "|", \ ++ { TPS_REG_INT_PLUG_EVENT, "PLUG_EVENT" }, \ ++ { TPS_REG_INT_POWER_STATUS_UPDATE, "POWER_STATUS_UPDATE" }, \ ++ { TPS_REG_INT_STATUS_UPDATE, "STATUS_UPDATE" }, \ ++ { TPS_REG_INT_PD_STATUS_UPDATE, "PD_STATUS_UPDATE" }) ++ + #define TPS6598X_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_STATUS_CONN_STATE_MASK | \ + TPS_STATUS_PP_5V0_SWITCH_MASK | \ + TPS_STATUS_PP_HV_SWITCH_MASK | \ +@@ -84,6 +91,14 @@ + TPS_STATUS_USB_HOST_PRESENT_MASK | \ + TPS_STATUS_LEGACY_MASK)) + ++#define TPS25750_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_STATUS_CONN_STATE_MASK | \ ++ GENMASK(19, 7) | \ ++ TPS_STATUS_VBUS_STATUS_MASK | \ ++ TPS_STATUS_USB_HOST_PRESENT_MASK | \ ++ TPS_STATUS_LEGACY_MASK | \ ++ BIT(26) | \ ++ GENMASK(31, 28))) ++ + #define show_status_conn_state(status) \ + __print_symbolic(TPS_STATUS_CONN_STATE((status)), \ + { TPS_STATUS_CONN_STATE_CONN_WITH_R_A, "conn-Ra" }, \ +@@ -141,6 +156,14 @@ + { TPS_STATUS_HIGH_VOLAGE_WARNING, "HIGH_VOLAGE_WARNING" }, \ + { TPS_STATUS_HIGH_LOW_VOLTAGE_WARNING, "HIGH_LOW_VOLTAGE_WARNING" }) + ++#define show_tps25750_status_flags(flags) \ ++ __print_flags((flags & TPS25750_STATUS_FLAGS_MASK), "|", \ ++ { TPS_STATUS_PLUG_PRESENT, "PLUG_PRESENT" }, \ ++ { TPS_STATUS_PLUG_UPSIDE_DOWN, "UPSIDE_DOWN" }, \ ++ { TPS_STATUS_PORTROLE, "PORTROLE" }, \ ++ { TPS_STATUS_DATAROLE, "DATAROLE" }, \ ++ { TPS_STATUS_BIST, "BIST" }) ++ + #define show_power_status_source_sink(power_status) \ + __print_symbolic(TPS_POWER_STATUS_SOURCESINK(power_status), \ + { 1, "sink" }, \ +@@ -159,6 +182,19 @@ + { TPS_POWER_STATUS_BC12_STATUS_CDP, "cdp" }, \ + { TPS_POWER_STATUS_BC12_STATUS_SDP, "sdp" }) + ++#define show_tps25750_power_status_charger_detect_status(power_status) \ ++ __print_symbolic(TPS25750_POWER_STATUS_CHARGER_DETECT_STATUS(power_status), \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_DISABLED, "disabled"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_IN_PROGRESS, "in progress"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_NONE, "none"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_SPD, "spd"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_BC_1_2_CPD, "cpd"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_BC_1_2_DPD, "dpd"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_DIV_1_DCP, "divider 1 dcp"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_DIV_2_DCP, "divider 2 dcp"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_DIV_3_DCP, "divider 3 dpc"}, \ ++ { TPS25750_POWER_STATUS_CHARGER_DET_STATUS_1_2V_DCP, "1.2V dpc"}) ++ + #define TPS_DATA_STATUS_FLAGS_MASK (GENMASK(31, 0) ^ (TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK | \ + TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK | \ + TPS_DATA_STATUS_TBT_CABLE_GEN_MASK)) +@@ -230,6 +266,21 @@ + show_cd321x_irq_flags(__entry->event)) + ); + ++TRACE_EVENT(tps25750_irq, ++ TP_PROTO(u64 event), ++ TP_ARGS(event), ++ ++ TP_STRUCT__entry( ++ __field(u64, event) ++ ), ++ ++ TP_fast_assign( ++ __entry->event = event; ++ ), ++ ++ TP_printk("event=%s", show_tps25750_irq_flags(__entry->event)) ++); ++ + TRACE_EVENT(tps6598x_status, + TP_PROTO(u32 status), + TP_ARGS(status), +@@ -257,6 +308,27 @@ + ) + ); + ++TRACE_EVENT(tps25750_status, ++ TP_PROTO(u32 status), ++ TP_ARGS(status), ++ ++ TP_STRUCT__entry( ++ __field(u32, status) ++ ), ++ ++ TP_fast_assign( ++ __entry->status = status; ++ ), ++ ++ TP_printk("conn: %s, vbus: %s, usb-host: %s, legacy: %s, flags: %s", ++ show_status_conn_state(__entry->status), ++ show_status_vbus_status(__entry->status), ++ show_status_usb_host_present(__entry->status), ++ show_status_legacy(__entry->status), ++ show_tps25750_status_flags(__entry->status) ++ ) ++); ++ + TRACE_EVENT(tps6598x_power_status, + TP_PROTO(u16 power_status), + TP_ARGS(power_status), +@@ -277,6 +349,26 @@ + ) + ); + ++TRACE_EVENT(tps25750_power_status, ++ TP_PROTO(u16 power_status), ++ TP_ARGS(power_status), ++ ++ TP_STRUCT__entry( ++ __field(u16, power_status) ++ ), ++ ++ TP_fast_assign( ++ __entry->power_status = power_status; ++ ), ++ ++ TP_printk("conn: %d, pwr-role: %s, typec: %s, charger detect: %s", ++ !!TPS_POWER_STATUS_CONNECTION(__entry->power_status), ++ show_power_status_source_sink(__entry->power_status), ++ show_power_status_typec_status(__entry->power_status), ++ show_tps25750_power_status_charger_detect_status(__entry->power_status) ++ ) ++); ++ + TRACE_EVENT(tps6598x_data_status, + TP_PROTO(u32 data_status), + TP_ARGS(data_status), +diff -Naur --no-dereference a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig +--- a/drivers/video/logo/Kconfig 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/video/logo/Kconfig 2024-03-28 11:26:09.901017460 -0400 +@@ -28,6 +28,10 @@ + bool "Standard 224-color Linux logo" + default y + ++config LOGO_BEAGLE_CLUT224 ++ bool "224-color Linux logo with BeagleBoard.org mascot Boris" ++ default y ++ + config LOGO_DEC_CLUT224 + bool "224-color Digital Equipment Corporation Linux logo" + depends on MACH_DECSTATION || ALPHA +diff -Naur --no-dereference a/drivers/video/logo/logo_beagle_clut224.ppm b/drivers/video/logo/logo_beagle_clut224.ppm +--- a/drivers/video/logo/logo_beagle_clut224.ppm 1969-12-31 19:00:00.000000000 -0500 ++++ b/drivers/video/logo/logo_beagle_clut224.ppm 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,1123 @@ ++P3 ++80 80 ++255 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 6 6 6 6 6 10 10 10 10 10 10 10 10 10 6 6 6 ++6 6 6 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 6 6 6 10 10 10 14 14 14 ++22 22 22 26 26 26 30 30 30 34 34 34 30 30 30 30 30 30 ++26 26 26 18 18 18 14 14 14 10 10 10 6 6 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 14 14 14 26 26 26 42 42 42 ++54 54 54 66 66 66 78 78 78 78 78 78 78 78 78 74 74 74 ++66 66 66 54 54 54 42 42 42 26 26 26 18 18 18 10 10 10 ++6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 10 10 10 22 22 22 42 42 42 66 66 66 86 86 86 ++66 66 66 38 38 38 38 38 38 22 22 22 26 26 26 34 34 34 ++54 54 54 66 66 66 86 86 86 70 70 70 46 46 46 26 26 26 ++14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++10 10 10 26 26 26 50 50 50 82 82 82 58 58 58 6 6 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 6 6 6 54 54 54 86 86 86 66 66 66 ++38 38 38 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 ++22 22 22 50 50 50 78 78 78 34 34 34 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 70 70 70 ++78 78 78 46 46 46 22 22 22 6 6 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 ++42 42 42 82 82 82 26 26 26 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 14 14 14 46 46 46 34 34 34 6 6 6 2 2 6 ++42 42 42 78 78 78 42 42 42 18 18 18 6 6 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 ++66 66 66 58 58 58 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 26 26 26 86 86 86 101 101 101 46 46 46 10 10 10 ++2 2 6 58 58 58 70 70 70 34 34 34 10 10 10 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 42 42 42 ++86 86 86 10 10 10 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 30 30 30 94 94 94 94 94 94 58 58 58 26 26 26 ++2 2 6 6 6 6 78 78 78 54 54 54 22 22 22 6 6 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 62 62 62 ++62 62 62 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 26 26 26 54 54 54 38 38 38 18 18 18 10 10 10 ++2 2 6 2 2 6 34 34 34 82 82 82 38 38 38 14 14 14 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 6 6 6 30 30 30 78 78 78 ++30 30 30 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 10 10 10 10 10 10 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 78 78 78 50 50 50 18 18 18 ++6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 38 38 38 86 86 86 ++14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 54 54 54 66 66 66 26 26 26 ++6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 14 14 42 42 42 82 82 82 ++2 2 6 2 2 6 2 2 6 6 6 6 10 10 10 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 6 6 6 14 14 14 10 10 10 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 18 18 18 82 82 82 34 34 34 ++10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 14 14 46 46 46 86 86 86 ++2 2 6 2 2 6 6 6 6 6 6 6 22 22 22 34 34 34 ++6 6 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++18 18 18 34 34 34 10 10 10 50 50 50 22 22 22 2 2 6 ++2 2 6 2 2 6 2 2 6 10 10 10 86 86 86 42 42 42 ++14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 14 14 46 46 46 86 86 86 ++2 2 6 2 2 6 38 38 38 116 116 116 94 94 94 22 22 22 ++22 22 22 2 2 6 2 2 6 2 2 6 14 14 14 86 86 86 ++138 138 138 162 162 162 158 155 152 38 38 38 26 26 26 6 6 6 ++2 2 6 2 2 6 2 2 6 2 2 6 86 86 86 46 46 46 ++14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 14 14 46 46 46 86 86 86 ++2 2 6 14 14 14 138 138 138 198 198 198 195 195 195 116 116 116 ++10 10 10 2 2 6 2 2 6 6 6 6 101 98 89 187 187 187 ++210 210 210 218 218 218 218 218 218 138 138 138 14 14 14 6 6 6 ++2 2 6 2 2 6 2 2 6 2 2 6 86 86 86 50 50 50 ++18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 14 14 46 46 46 86 86 86 ++2 2 6 54 54 54 218 218 218 195 195 195 226 226 226 246 246 246 ++58 58 58 2 2 6 2 2 6 30 30 30 210 210 210 253 253 253 ++171 170 170 123 123 123 221 221 221 234 234 234 74 74 74 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 58 58 58 ++22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 14 14 46 46 46 82 82 82 ++2 2 6 106 106 106 171 170 170 26 26 26 86 86 86 226 226 226 ++123 123 123 10 10 10 14 14 14 46 46 46 231 231 231 190 190 190 ++6 6 6 70 70 70 90 90 90 238 238 238 158 158 158 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 58 58 58 ++22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 14 14 42 42 42 86 86 86 ++6 6 6 116 116 116 106 106 106 6 6 6 70 70 70 144 144 144 ++128 128 128 18 18 18 38 38 38 54 54 54 221 221 221 106 106 106 ++2 2 6 14 14 14 46 46 46 190 190 190 198 198 198 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 74 74 74 62 62 62 ++22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 14 14 14 42 42 42 94 94 94 ++14 14 14 101 101 101 128 128 128 2 2 6 18 18 18 116 116 116 ++118 98 46 121 92 8 121 92 8 98 77 21 162 162 162 106 106 106 ++2 2 6 2 2 6 2 2 6 195 195 195 195 195 195 6 6 6 ++2 2 6 2 2 6 2 2 6 2 2 6 74 74 74 62 62 62 ++22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 ++0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 38 38 38 90 90 90 ++14 14 14 58 58 58 210 210 210 26 26 26 61 42 6 156 107 11 ++226 170 11 236 186 11 225 175 15 184 144 12 225 175 15 175 146 61 ++37 26 9 2 2 6 70 70 70 246 246 246 138 138 138 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 70 70 70 66 66 66 ++26 26 26 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 38 38 38 86 86 86 ++14 14 14 10 10 10 195 195 195 188 164 115 192 133 9 225 175 15 ++239 182 13 236 186 11 232 195 16 232 195 16 246 215 20 241 208 19 ++232 195 16 184 144 12 218 194 134 219 214 185 42 42 42 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 50 50 50 74 74 74 ++30 30 30 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 86 86 86 ++14 14 14 2 2 6 121 87 25 192 133 9 219 162 10 239 182 13 ++236 186 11 232 195 16 241 208 19 246 215 20 246 215 20 246 215 20 ++246 215 20 241 208 19 241 208 19 226 184 13 121 87 25 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 50 50 50 82 82 82 ++34 34 34 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 82 82 82 ++30 30 30 61 42 6 180 123 7 206 145 10 230 174 11 239 182 13 ++236 186 11 238 202 15 241 208 19 235 218 115 246 215 20 246 215 20 ++246 215 20 246 215 20 226 184 13 225 175 15 184 144 12 6 6 6 ++2 2 6 2 2 6 2 2 6 2 2 6 26 26 26 94 94 94 ++42 42 42 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 78 78 78 ++50 50 50 104 69 6 192 133 9 216 158 10 236 178 12 236 186 11 ++232 195 16 241 208 19 246 215 20 246 215 20 246 215 20 246 215 20 ++241 208 19 200 144 11 200 144 11 216 158 10 163 110 8 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 90 90 90 ++54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 30 30 30 78 78 78 ++46 46 46 22 22 22 137 92 6 210 162 10 239 182 13 236 186 11 ++238 202 15 241 208 19 246 215 20 246 215 20 241 208 19 210 162 10 ++185 133 11 210 150 10 216 158 10 210 150 10 104 69 6 2 2 6 ++6 6 6 54 54 54 14 14 14 2 2 6 2 2 6 62 62 62 ++74 74 74 30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 34 34 34 78 78 78 ++50 50 50 6 6 6 92 69 23 138 101 21 190 146 13 226 184 13 ++232 195 16 232 195 16 225 175 15 190 146 13 167 114 7 192 133 9 ++210 150 10 213 154 11 190 142 34 188 164 115 101 98 89 2 2 6 ++2 2 6 78 78 78 116 116 116 58 58 58 2 2 6 22 22 22 ++90 90 90 46 46 46 18 18 18 6 6 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 38 38 38 86 86 86 ++50 50 50 6 6 6 128 128 128 172 154 116 156 107 11 167 114 7 ++200 144 11 184 144 12 197 138 11 200 144 11 206 145 10 206 145 10 ++197 138 11 188 164 115 195 195 195 198 198 198 171 170 170 14 14 14 ++2 2 6 22 22 22 116 116 116 116 116 116 22 22 22 2 2 6 ++74 74 74 70 70 70 30 30 30 10 10 10 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 18 18 18 50 50 50 101 101 101 ++26 26 26 10 10 10 138 138 138 190 190 190 172 154 116 156 107 11 ++197 138 11 200 144 11 197 138 11 192 133 9 180 123 7 190 142 34 ++181 170 141 187 187 187 202 202 202 221 221 221 218 218 218 66 66 66 ++2 2 6 2 2 6 50 50 50 62 62 62 6 6 6 2 2 6 ++10 10 10 90 90 90 50 50 50 18 18 18 6 6 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 10 10 10 34 34 34 74 74 74 74 74 74 ++2 2 6 6 6 6 144 144 144 198 198 198 190 190 190 181 170 141 ++150 121 62 156 107 11 156 107 11 166 123 43 172 154 116 187 187 187 ++190 190 190 210 210 210 246 246 246 253 253 253 253 253 253 182 182 182 ++6 6 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 62 62 62 74 74 74 34 34 34 14 14 14 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 10 10 10 22 22 22 54 54 54 94 94 94 18 18 18 ++2 2 6 46 46 46 234 234 234 221 221 221 190 190 190 190 190 190 ++190 190 190 187 187 187 187 187 187 190 190 190 190 190 190 195 195 195 ++218 218 218 242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 ++82 82 82 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 14 14 14 86 86 86 54 54 54 22 22 22 6 6 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 6 6 18 18 18 46 46 46 90 90 90 46 46 46 18 18 18 ++6 6 6 182 182 182 253 253 253 246 246 246 206 206 206 190 190 190 ++190 190 190 190 190 190 190 190 190 190 190 190 206 206 206 231 231 231 ++250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++202 202 202 14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 42 42 42 86 86 86 42 42 42 18 18 18 ++6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 ++14 14 14 38 38 38 74 74 74 66 66 66 2 2 6 6 6 6 ++90 90 90 250 250 250 253 253 253 253 253 253 238 238 238 138 138 138 ++97 87 74 110 93 64 119 103 79 103 95 84 108 105 106 238 238 238 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 82 82 82 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 78 78 78 70 70 70 34 34 34 ++14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 ++34 34 34 66 66 66 78 78 78 6 6 6 2 2 6 18 18 18 ++218 218 218 253 253 253 253 253 253 210 210 210 80 72 61 103 75 39 ++169 127 44 169 127 44 167 127 47 207 184 137 167 127 47 104 86 63 ++234 234 234 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 182 182 182 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 18 18 18 90 90 90 62 62 62 ++30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 ++58 58 58 90 90 90 18 18 18 2 2 6 2 2 6 108 105 106 ++253 253 253 253 253 253 218 218 218 103 75 39 169 127 44 143 114 43 ++118 84 23 169 127 44 169 127 44 188 164 115 183 152 86 169 127 44 ++97 87 74 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 231 231 231 18 18 18 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 18 18 18 94 94 94 ++54 54 54 26 26 26 10 10 10 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 6 6 6 22 22 22 50 50 50 ++90 90 90 26 26 26 2 2 6 2 2 6 14 14 14 195 195 195 ++250 250 250 253 253 253 89 81 69 166 123 43 169 127 44 169 127 44 ++98 77 21 163 123 43 120 94 48 156 118 43 225 216 182 161 124 51 ++80 72 61 171 170 170 253 253 253 253 253 253 253 253 253 253 253 253 ++250 250 250 242 242 242 54 54 54 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 38 38 38 ++86 86 86 50 50 50 22 22 22 6 6 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 14 14 14 38 38 38 82 82 82 ++34 34 34 2 2 6 2 2 6 2 2 6 42 42 42 195 195 195 ++246 246 246 231 231 231 104 86 51 169 127 44 169 127 44 169 127 44 ++121 87 25 105 82 38 72 65 62 105 82 38 211 190 148 239 232 219 ++154 139 110 89 81 69 210 210 210 250 250 250 246 246 246 238 238 238 ++226 226 226 231 231 231 101 101 101 6 6 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++38 38 38 82 82 82 42 42 42 14 14 14 6 6 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 10 10 10 26 26 26 62 62 62 66 66 66 ++2 2 6 2 2 6 2 2 6 6 6 6 70 70 70 171 170 170 ++206 206 206 101 98 89 157 117 39 169 127 44 169 127 44 169 127 44 ++163 123 43 105 82 38 163 123 43 169 127 44 211 190 148 255 255 255 ++255 255 255 253 253 253 144 144 144 90 90 90 190 190 190 202 202 202 ++198 198 198 202 202 202 182 182 182 18 18 18 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 62 62 62 66 66 66 30 30 30 10 10 10 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 14 14 42 42 42 82 82 82 18 18 18 ++2 2 6 2 2 6 2 2 6 10 10 10 94 94 94 182 182 182 ++210 210 210 99 81 49 169 127 44 169 127 44 169 127 44 169 127 44 ++169 127 44 98 77 21 169 127 44 188 164 115 252 252 252 255 255 255 ++255 255 255 255 255 255 255 255 255 158 155 152 108 105 106 138 138 138 ++195 195 195 195 195 195 210 210 210 158 158 158 6 6 6 14 14 14 ++50 50 50 14 14 14 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 6 6 6 86 86 86 46 46 46 18 18 18 6 6 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 6 6 22 22 22 54 54 54 70 70 70 2 2 6 ++2 2 6 10 10 10 2 2 6 22 22 22 169 168 166 231 231 231 ++128 128 128 143 114 43 169 127 44 169 127 44 169 127 44 169 127 44 ++169 127 44 118 84 23 167 127 47 247 245 242 255 255 255 255 255 255 ++255 255 255 255 255 255 182 182 182 116 116 116 128 128 128 38 38 38 ++206 206 206 206 206 206 198 198 198 226 226 226 94 94 94 2 2 6 ++6 6 6 38 38 38 30 30 30 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 62 62 62 66 66 66 26 26 26 10 10 10 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 10 10 10 30 30 30 74 74 74 50 50 50 2 2 6 ++26 26 26 26 26 26 2 2 6 106 106 106 238 238 238 253 253 253 ++89 81 66 169 127 44 169 127 44 169 127 44 169 127 44 169 127 44 ++169 127 44 157 117 39 138 113 67 255 255 255 255 255 255 255 255 255 ++255 255 255 255 255 255 202 202 202 50 50 50 34 34 34 50 50 50 ++231 231 231 246 246 246 218 218 218 202 202 202 210 210 210 14 14 14 ++2 2 6 2 2 6 30 30 30 22 22 22 2 2 6 2 2 6 ++2 2 6 2 2 6 18 18 18 86 86 86 42 42 42 14 14 14 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 14 14 42 42 42 90 90 90 22 22 22 2 2 6 ++42 42 42 2 2 6 18 18 18 218 218 218 253 253 253 253 253 253 ++104 86 63 169 127 44 169 127 44 169 127 44 169 127 44 169 127 44 ++166 123 43 156 118 43 105 82 38 255 255 255 255 255 255 255 255 255 ++255 255 255 255 255 255 255 255 255 221 221 221 182 182 182 90 90 90 ++232 232 232 253 253 253 248 248 248 221 221 221 218 218 218 101 101 101 ++2 2 6 14 14 14 18 18 18 38 38 38 10 10 10 2 2 6 ++2 2 6 2 2 6 2 2 6 78 78 78 58 58 58 22 22 22 ++6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 6 6 18 18 18 54 54 54 82 82 82 2 2 6 26 26 26 ++22 22 22 2 2 6 123 123 123 253 253 253 253 253 253 253 253 253 ++89 81 66 169 127 44 169 127 44 169 127 44 169 127 44 166 123 43 ++141 109 45 157 117 39 118 84 23 240 237 231 255 255 255 255 255 255 ++255 255 255 255 255 255 255 255 255 226 226 226 97 87 74 72 54 38 ++253 253 253 253 253 253 251 251 250 250 250 250 238 238 238 198 198 198 ++6 6 6 38 38 38 58 58 58 26 26 26 38 38 38 2 2 6 ++2 2 6 2 2 6 2 2 6 46 46 46 78 78 78 30 30 30 ++10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++10 10 10 30 30 30 74 74 74 58 58 58 2 2 6 42 42 42 ++2 2 6 22 22 22 231 231 231 253 253 253 253 253 253 253 253 253 ++162 161 160 104 86 51 169 127 44 169 127 44 156 118 43 141 109 45 ++145 111 45 105 82 38 157 117 39 216 197 160 255 255 255 203 202 203 ++158 155 152 116 116 116 72 65 62 95 51 32 175 118 6 145 90 47 ++250 250 250 253 253 253 252 252 252 253 253 253 253 253 253 246 246 246 ++46 46 46 38 38 38 42 42 42 14 14 14 38 38 38 14 14 14 ++2 2 6 2 2 6 2 2 6 6 6 6 86 86 86 46 46 46 ++14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 ++14 14 14 42 42 42 90 90 90 18 18 18 18 18 18 26 26 26 ++2 2 6 116 116 116 253 253 253 253 253 253 253 253 253 253 253 253 ++248 248 248 138 138 138 99 81 49 105 82 38 125 96 44 121 87 25 ++98 77 21 125 96 44 169 127 44 216 197 160 255 255 255 190 190 190 ++108 105 106 70 70 70 58 58 58 72 54 38 192 133 9 120 94 48 ++250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++94 94 94 6 6 6 2 2 6 2 2 6 10 10 10 34 34 34 ++2 2 6 2 2 6 2 2 6 2 2 6 74 74 74 58 58 58 ++22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 ++26 26 26 66 66 66 82 82 82 2 2 6 38 38 38 6 6 6 ++14 14 14 210 210 210 253 253 253 253 253 253 253 253 253 253 253 253 ++101 101 101 90 90 90 244 244 244 89 81 69 145 111 45 161 124 51 ++197 178 128 207 184 137 216 197 160 218 218 218 171 170 170 151 148 137 ++141 130 107 80 72 61 169 168 166 226 226 226 109 101 93 187 187 187 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++144 144 144 2 2 6 2 2 6 2 2 6 2 2 6 46 46 46 ++2 2 6 2 2 6 2 2 6 2 2 6 42 42 42 74 74 74 ++30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 14 14 14 ++42 42 42 90 90 90 26 26 26 6 6 6 42 42 42 2 2 6 ++74 74 74 250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 ++106 106 106 131 116 91 210 209 209 110 93 64 169 127 44 233 229 220 ++255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 239 232 219 ++169 127 44 120 94 48 244 244 244 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++182 182 182 2 2 6 2 2 6 2 2 6 2 2 6 46 46 46 ++2 2 6 2 2 6 2 2 6 2 2 6 10 10 10 86 86 86 ++38 38 38 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 ++66 66 66 82 82 82 2 2 6 22 22 22 18 18 18 2 2 6 ++144 144 144 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++171 170 170 125 96 44 103 95 84 110 93 64 175 146 61 255 255 255 ++255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 ++183 152 86 145 111 45 195 195 194 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 252 252 252 253 253 253 253 253 253 253 253 253 ++206 206 206 2 2 6 2 2 6 2 2 6 2 2 6 38 38 38 ++2 2 6 2 2 6 2 2 6 2 2 6 6 6 6 86 86 86 ++46 46 46 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 6 6 6 18 18 18 46 46 46 ++86 86 86 18 18 18 2 2 6 34 34 34 10 10 10 6 6 6 ++210 210 210 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++246 246 246 100 88 68 145 111 45 120 94 48 159 135 84 249 249 249 ++255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 ++152 137 111 156 118 43 158 158 158 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 251 251 250 253 253 253 253 253 253 253 253 253 ++221 221 221 6 6 6 2 2 6 2 2 6 6 6 6 30 30 30 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 82 82 82 ++54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 26 26 26 66 66 66 ++62 62 62 2 2 6 2 2 6 38 38 38 10 10 10 26 26 26 ++238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 144 144 144 138 113 67 166 123 43 138 119 85 246 246 246 ++255 255 255 242 242 242 255 255 255 255 255 255 234 234 234 255 255 255 ++152 137 111 156 118 43 162 161 160 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 250 250 250 253 253 253 253 253 253 253 253 253 ++231 231 231 6 6 6 2 2 6 2 2 6 10 10 10 30 30 30 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 66 66 66 ++58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 10 10 10 38 38 38 78 78 78 ++6 6 6 2 2 6 2 2 6 46 46 46 14 14 14 42 42 42 ++246 246 246 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 250 250 250 94 90 86 154 122 46 138 119 85 253 253 253 ++244 243 244 195 195 194 255 255 255 244 244 244 182 182 182 255 255 255 ++147 140 128 145 111 45 187 187 187 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 249 249 249 249 249 249 253 253 253 253 253 253 ++234 234 234 10 10 10 2 2 6 2 2 6 22 22 22 14 14 14 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 66 66 66 ++62 62 62 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 18 18 18 50 50 50 74 74 74 ++2 2 6 2 2 6 14 14 14 70 70 70 34 34 34 62 62 62 ++250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 231 231 231 104 86 63 141 130 107 255 255 255 ++246 246 246 182 182 182 255 255 255 231 231 231 196 195 196 255 255 255 ++147 140 128 119 100 63 242 242 242 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 242 242 242 253 253 253 253 253 253 ++234 234 234 14 14 14 2 2 6 2 2 6 30 30 30 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 66 66 66 ++62 62 62 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 18 18 18 54 54 54 62 62 62 ++2 2 6 2 2 6 2 2 6 30 30 30 46 46 46 70 70 70 ++250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 210 210 210 89 81 66 152 137 111 255 255 255 ++254 254 254 171 170 170 255 255 255 218 218 218 210 209 209 255 255 255 ++151 148 137 123 99 54 169 168 166 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 252 252 252 253 253 253 253 253 253 ++226 226 226 10 10 10 2 2 6 6 6 6 30 30 30 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 66 66 66 ++58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 22 22 22 58 58 58 62 62 62 ++2 2 6 2 2 6 2 2 6 2 2 6 30 30 30 78 78 78 ++250 250 250 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 249 249 249 97 87 74 169 127 44 152 137 111 255 255 255 ++255 255 255 171 170 170 255 255 255 203 202 203 226 226 226 255 255 255 ++158 155 152 169 127 44 120 94 48 234 234 234 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++206 206 206 2 2 6 22 22 22 34 34 34 18 14 6 22 22 22 ++26 26 26 18 18 18 6 6 6 2 2 6 2 2 6 82 82 82 ++54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 26 26 26 62 62 62 106 106 106 ++78 53 15 185 133 11 210 162 10 121 92 8 6 6 6 62 62 62 ++238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 238 238 238 110 93 64 166 123 43 162 161 160 255 255 255 ++255 255 255 108 105 106 94 94 94 82 82 82 244 244 244 255 255 255 ++202 202 202 150 121 62 141 109 45 202 202 202 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++158 158 158 18 18 18 14 14 14 2 2 6 2 2 6 2 2 6 ++6 6 6 18 18 18 66 66 66 38 38 38 6 6 6 94 94 94 ++50 50 50 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 ++10 10 10 10 10 10 18 18 18 38 38 38 78 78 78 141 130 107 ++216 158 10 242 186 14 246 190 14 246 190 14 163 110 8 10 10 10 ++90 90 90 238 238 238 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 252 252 252 144 144 144 80 72 61 218 218 218 255 255 255 ++206 206 206 123 123 123 253 253 253 128 128 128 169 168 166 254 254 254 ++254 254 254 101 98 89 128 128 128 252 252 252 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 225 216 182 219 191 94 219 191 94 ++180 133 36 37 26 9 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 38 38 38 46 46 46 26 26 26 106 106 106 ++54 54 54 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 6 6 6 14 14 14 22 22 22 ++30 30 30 38 38 38 50 50 50 70 70 70 106 106 106 190 142 34 ++226 170 11 242 186 14 246 190 14 246 190 14 246 190 14 156 107 11 ++6 6 6 74 74 74 226 226 226 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 182 182 182 108 105 106 116 116 116 ++123 123 123 244 244 244 253 253 253 244 244 244 128 128 128 116 116 116 ++116 116 116 169 168 166 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 201 174 68 241 196 14 241 208 19 ++232 195 16 38 30 10 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 6 6 6 30 30 30 26 26 26 210 162 10 159 135 84 ++66 66 66 26 26 26 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 18 18 18 38 38 38 58 58 58 ++78 78 78 86 86 86 101 101 101 123 123 123 175 146 61 210 150 10 ++234 174 13 246 186 14 246 190 14 246 190 14 246 190 14 236 186 11 ++104 69 6 2 2 6 46 46 46 198 198 198 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 234 234 234 242 242 242 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 201 174 68 242 186 14 241 196 14 ++210 162 10 22 18 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 6 6 6 121 92 8 238 202 15 232 195 16 ++82 82 82 34 34 34 10 10 10 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 14 14 14 38 38 38 70 70 70 154 122 46 ++190 142 34 200 144 11 197 138 11 197 138 11 213 154 11 226 170 11 ++242 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++225 175 15 45 32 11 2 2 6 22 22 22 158 158 158 250 250 250 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 250 250 250 242 242 242 201 174 68 239 182 13 236 186 11 ++213 154 11 45 32 11 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 61 42 6 225 175 15 236 186 11 236 186 11 ++119 103 79 42 42 42 14 14 14 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 6 6 22 22 22 54 54 54 154 122 46 213 154 11 ++226 170 11 230 174 11 226 170 11 226 170 11 236 178 12 242 186 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++241 196 14 184 144 12 10 10 10 2 2 6 6 6 6 116 116 116 ++242 242 242 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 231 231 231 198 198 198 201 174 68 236 178 12 236 178 12 ++210 150 10 137 92 6 18 14 6 2 2 6 2 2 6 2 2 6 ++6 6 6 61 42 6 200 144 11 236 178 12 239 182 13 239 182 13 ++124 112 88 58 58 58 22 22 22 6 6 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 10 10 10 30 30 30 70 70 70 180 133 36 226 170 11 ++239 182 13 242 186 14 242 186 14 246 186 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 232 195 16 104 69 6 2 2 6 2 2 6 2 2 6 ++66 66 66 221 221 221 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 206 206 206 198 198 198 201 174 68 230 174 11 230 174 11 ++216 158 10 192 133 9 163 110 8 116 81 8 104 69 6 116 81 8 ++167 114 7 197 138 11 226 170 11 239 182 13 242 186 14 242 186 14 ++165 145 105 78 78 78 34 34 34 14 14 14 6 6 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 6 6 30 30 30 78 78 78 190 142 34 226 170 11 ++239 182 13 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 241 196 14 210 162 10 22 18 6 2 2 6 2 2 6 ++2 2 6 38 38 38 218 218 218 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++250 250 250 206 206 206 198 198 198 201 174 68 226 170 11 236 178 12 ++224 166 10 210 150 10 200 144 11 197 138 11 192 133 9 197 138 11 ++210 150 10 226 170 11 242 186 14 246 190 14 246 190 14 246 186 14 ++225 175 15 124 112 88 62 62 62 30 30 30 14 14 14 6 6 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 10 10 10 30 30 30 78 78 78 167 127 47 224 166 10 ++239 182 13 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 241 196 14 138 101 21 2 2 6 2 2 6 ++2 2 6 2 2 6 78 78 78 250 250 250 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++250 250 250 218 218 218 198 198 198 190 142 34 219 162 10 236 178 12 ++234 174 13 224 166 10 216 158 10 213 154 11 213 154 11 216 158 10 ++226 170 11 239 182 13 246 190 14 246 190 14 246 190 14 246 190 14 ++242 186 14 197 166 45 101 101 101 58 58 58 30 30 30 14 14 14 ++6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 10 10 10 30 30 30 74 74 74 167 127 47 216 158 10 ++236 178 12 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 241 196 14 226 184 13 61 42 6 2 2 6 ++2 2 6 2 2 6 22 22 22 238 238 238 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 226 226 226 187 187 187 180 133 36 216 158 10 236 178 12 ++239 182 13 236 178 12 230 174 11 226 170 11 226 170 11 230 174 11 ++236 178 12 242 186 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 186 14 239 182 13 197 166 45 106 106 106 66 66 66 34 34 34 ++14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 6 6 26 26 26 70 70 70 163 133 67 213 154 11 ++236 178 12 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 241 196 14 190 146 13 18 14 6 ++2 2 6 2 2 6 46 46 46 246 246 246 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 221 221 221 86 86 86 156 107 11 216 158 10 236 178 12 ++242 186 14 246 186 14 242 186 14 239 182 13 239 182 13 242 186 14 ++242 186 14 246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 242 186 14 225 175 15 142 114 66 66 66 66 ++30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 6 6 26 26 26 70 70 70 163 133 67 210 150 10 ++236 178 12 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 232 195 16 121 92 8 ++34 34 34 106 106 106 221 221 221 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++242 242 242 82 82 82 18 14 6 163 110 8 216 158 10 236 178 12 ++242 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 163 133 67 ++46 46 46 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 10 10 10 30 30 30 78 78 78 163 133 67 210 150 10 ++236 178 12 246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 241 196 14 225 175 15 ++181 170 141 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 218 218 218 ++58 58 58 2 2 6 22 18 6 167 114 7 216 158 10 236 178 12 ++246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 186 14 242 186 14 190 142 34 ++54 54 54 22 22 22 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 14 14 38 38 38 86 86 86 180 133 36 213 154 11 ++236 178 12 246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 232 195 16 ++190 146 13 218 218 218 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 250 250 250 171 170 170 26 26 26 ++2 2 6 2 2 6 37 26 9 163 110 8 219 162 10 239 182 13 ++246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 186 14 236 178 12 224 166 10 142 114 66 ++46 46 46 18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 6 6 18 18 18 50 50 50 109 101 93 192 133 9 224 166 10 ++242 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 242 186 14 226 184 13 ++210 162 10 141 109 45 226 226 226 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 ++253 253 253 253 253 253 198 198 198 66 66 66 2 2 6 2 2 6 ++2 2 6 2 2 6 45 32 11 156 107 11 219 162 10 239 182 13 ++246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 242 186 14 234 174 13 213 154 11 154 122 46 66 66 66 ++30 30 30 10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 6 6 22 22 22 58 58 58 150 121 62 206 145 10 234 174 13 ++242 186 14 246 186 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 236 178 12 ++210 162 10 163 110 8 61 42 6 138 138 138 218 218 218 250 250 250 ++253 253 253 253 253 253 253 253 253 250 250 250 242 242 242 210 210 210 ++144 144 144 66 66 66 6 6 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 61 42 6 163 110 8 216 158 10 236 178 12 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 239 182 13 ++230 174 11 216 158 10 190 142 34 124 112 88 70 70 70 38 38 38 ++18 18 18 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 6 6 22 22 22 62 62 62 166 123 43 206 145 10 224 166 10 ++236 178 12 239 182 13 242 186 14 242 186 14 246 186 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 236 178 12 ++216 158 10 175 118 6 78 53 15 2 2 6 6 6 6 30 30 30 ++54 54 54 62 62 62 50 50 50 38 38 38 14 14 14 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 6 6 6 78 53 15 167 114 7 213 154 11 236 178 12 ++246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 246 190 14 ++246 190 14 242 186 14 239 182 13 239 182 13 230 174 11 210 150 10 ++167 127 47 124 112 88 82 82 82 54 54 54 34 34 34 18 18 18 ++6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 6 6 18 18 18 50 50 50 157 117 39 192 133 9 200 144 11 ++216 158 10 219 162 10 224 166 10 226 170 11 230 174 11 236 178 12 ++239 182 13 239 182 13 242 186 14 246 186 14 246 190 14 246 190 14 ++246 190 14 246 190 14 246 190 14 246 190 14 246 186 14 230 174 11 ++210 150 10 163 110 8 104 69 6 10 10 10 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 6 6 6 85 60 19 167 114 7 206 145 10 230 174 11 ++242 186 14 246 190 14 246 190 14 246 190 14 246 186 14 242 186 14 ++239 182 13 230 174 11 224 166 10 213 154 11 180 133 36 124 112 88 ++86 86 86 58 58 58 38 38 38 22 22 22 10 10 10 6 6 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 14 14 14 34 34 34 70 70 70 141 109 45 157 117 39 ++167 114 7 180 123 7 192 133 9 197 138 11 200 144 11 206 145 10 ++213 154 11 219 162 10 224 166 10 230 174 11 239 182 13 242 186 14 ++246 186 14 246 186 14 246 186 14 246 186 14 239 182 13 216 158 10 ++185 133 11 152 99 6 104 69 6 18 14 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 2 2 6 ++2 2 6 6 6 6 78 53 15 152 99 6 192 133 9 219 162 10 ++236 178 12 239 182 13 246 186 14 242 186 14 239 182 13 236 178 12 ++224 166 10 206 145 10 192 133 9 150 121 62 94 94 94 62 62 62 ++42 42 42 22 22 22 14 14 14 6 6 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 6 6 18 18 18 34 34 34 58 58 58 78 78 78 ++101 98 89 124 112 88 141 109 45 156 107 11 163 110 8 167 114 7 ++175 118 6 180 123 7 185 133 11 197 138 11 210 150 10 219 162 10 ++226 170 11 236 178 12 236 178 12 234 174 13 219 162 10 197 138 11 ++163 110 8 137 92 6 85 60 19 10 10 10 2 2 6 2 2 6 ++18 18 18 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 ++38 38 38 38 38 38 38 38 38 38 38 38 26 26 26 2 2 6 ++2 2 6 6 6 6 61 42 6 137 92 6 175 118 6 200 144 11 ++219 162 10 230 174 11 234 174 13 230 174 11 219 162 10 210 150 10 ++192 133 9 163 110 8 124 112 88 82 82 82 50 50 50 30 30 30 ++14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 14 14 14 22 22 22 34 34 34 ++42 42 42 58 58 58 74 74 74 86 86 86 101 98 89 119 100 63 ++125 96 44 121 87 25 137 92 6 152 99 6 163 110 8 180 123 7 ++185 133 11 197 138 11 206 145 10 200 144 11 180 123 7 156 107 11 ++137 92 6 104 69 6 45 32 11 54 54 54 108 105 106 101 98 89 ++86 86 86 82 82 82 78 78 78 78 78 78 78 78 78 78 78 78 ++78 78 78 78 78 78 78 78 78 82 82 82 86 86 86 94 94 94 ++106 106 106 101 101 101 86 66 32 116 81 8 156 107 11 180 123 7 ++192 133 9 200 144 11 206 145 10 200 144 11 192 133 9 175 118 6 ++138 101 21 109 101 93 70 70 70 42 42 42 22 22 22 10 10 10 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 10 10 10 ++14 14 14 22 22 22 30 30 30 38 38 38 50 50 50 62 62 62 ++74 74 74 90 90 90 101 98 89 119 103 79 121 87 25 116 81 8 ++137 92 6 152 99 6 152 99 6 152 99 6 137 92 6 116 81 8 ++104 69 6 86 66 32 101 98 89 82 82 82 58 58 58 46 46 46 ++38 38 38 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 ++34 34 34 34 34 34 34 34 34 34 34 34 38 38 38 42 42 42 ++54 54 54 82 82 82 97 87 74 85 60 19 137 92 6 156 107 11 ++167 114 7 175 118 6 175 118 6 167 114 7 152 99 6 121 87 25 ++101 98 89 62 62 62 34 34 34 18 18 18 6 6 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 6 6 6 6 6 10 10 10 18 18 18 22 22 22 ++30 30 30 42 42 42 50 50 50 66 66 66 86 86 86 101 98 89 ++104 86 63 104 69 6 104 69 6 104 69 6 104 69 6 85 60 19 ++86 66 32 90 90 90 62 62 62 38 38 38 22 22 22 14 14 14 ++10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 ++6 6 6 10 10 10 10 10 10 10 10 10 10 10 10 14 14 14 ++22 22 22 42 42 42 70 70 70 89 81 66 78 53 15 104 69 6 ++116 81 8 137 92 6 137 92 6 116 81 8 99 81 49 86 86 86 ++58 58 58 30 30 30 14 14 14 6 6 6 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 ++10 10 10 14 14 14 18 18 18 26 26 26 38 38 38 54 54 54 ++70 70 70 86 86 86 97 87 74 89 81 66 89 81 66 86 86 86 ++74 74 74 50 50 50 30 30 30 14 14 14 6 6 6 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++6 6 6 18 18 18 34 34 34 58 58 58 82 82 82 89 81 66 ++89 81 66 89 81 66 100 88 68 97 87 74 74 74 74 50 50 50 ++26 26 26 14 14 14 6 6 6 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 6 6 6 6 6 6 14 14 14 18 18 18 ++30 30 30 38 38 38 46 46 46 54 54 54 50 50 50 42 42 42 ++30 30 30 18 18 18 10 10 10 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 6 6 6 14 14 14 26 26 26 38 38 38 50 50 50 ++58 58 58 58 58 58 54 54 54 42 42 42 30 30 30 18 18 18 ++10 10 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6 6 6 ++6 6 6 10 10 10 14 14 14 18 18 18 18 18 18 14 14 14 ++10 10 10 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 6 6 6 14 14 14 18 18 18 ++22 22 22 22 22 22 18 18 18 14 14 14 10 10 10 6 6 6 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ++0 0 0 0 0 0 +diff -Naur --no-dereference a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c +--- a/drivers/video/logo/logo.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/video/logo/logo.c 2024-03-28 11:26:09.901017460 -0400 +@@ -100,6 +100,10 @@ + /* SuperH Linux logo */ + logo = &logo_superh_clut224; + #endif ++#ifdef CONFIG_LOGO_BEAGLE_CLUT224 ++ /* Generic Linux logo */ ++ logo = &logo_beagle_clut224; ++#endif + } + return logo; + } +diff -Naur --no-dereference a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile +--- a/drivers/video/logo/Makefile 2024-01-31 19:19:14.000000000 -0500 ++++ b/drivers/video/logo/Makefile 2024-03-28 11:26:09.901017460 -0400 +@@ -5,6 +5,7 @@ + obj-$(CONFIG_LOGO_LINUX_MONO) += logo_linux_mono.o + obj-$(CONFIG_LOGO_LINUX_VGA16) += logo_linux_vga16.o + obj-$(CONFIG_LOGO_LINUX_CLUT224) += logo_linux_clut224.o ++obj-$(CONFIG_LOGO_BEAGLE_CLUT224) += logo_beagle_clut224.o + obj-$(CONFIG_LOGO_DEC_CLUT224) += logo_dec_clut224.o + obj-$(CONFIG_LOGO_MAC_CLUT224) += logo_mac_clut224.o + obj-$(CONFIG_LOGO_PARISC_CLUT224) += logo_parisc_clut224.o +diff -Naur --no-dereference a/firmware/am335x-bone-scale-data.bin b/firmware/am335x-bone-scale-data.bin +--- a/firmware/am335x-bone-scale-data.bin 1969-12-31 19:00:00.000000000 -0500 ++++ b/firmware/am335x-bone-scale-data.bin 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1 @@ ++ W#d$ m$$ m$$ l$†$ l$†d$ m$$ m$$ l$†$ l$† +\ No newline at end of file +diff -Naur --no-dereference a/firmware/am335x-evm-scale-data.bin b/firmware/am335x-evm-scale-data.bin +--- a/firmware/am335x-evm-scale-data.bin 1969-12-31 19:00:00.000000000 -0500 ++++ b/firmware/am335x-evm-scale-data.bin 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1 @@ ++ Wd-%d-%+ +\ No newline at end of file +diff -Naur --no-dereference a/firmware/am335x-pm-firmware.bin b/firmware/am335x-pm-firmware.bin +--- a/firmware/am335x-pm-firmware.bin 1969-12-31 19:00:00.000000000 -0500 ++++ b/firmware/am335x-pm-firmware.bin 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,34 @@ ++™ é í ñ õ ù ý   • • • • • • • • • • • • • • • • • É • • • • • • • • • • • • • • å • E Y ± • • • Å Ù í )=Qey¡µÉJh CôÉs`pG0áDð<¹KD›hpG¿ÊD8K D›`pG¿ÊD8KJh›²`pG,áDœKhZ* ØJëƒëƒ˜h0¿ pG pG¿œ#J$Khhð´#Mð"J/`"NÃóÀp!L"HÃó!JÃó€%7`ÃóÀ#p%pHhJh `Sh ÐHI€è0P`˜D냛hHð¼GiðÑI h)ИIÄë„dh±T`éçI˜ÄQø$@,öÑáç<áD8áD°™¬˜¨0áD4áDœ¸Oðÿ3´HLIJ#``]øK ``pG4áD0áD8áD<áDJh CôÉs`pG0áDJh›²Cê@`pG¿,áDJh#ðÿC`pG¿@áDKJhëƒëƒ|pG¿œKJhëƒëƒX|pG¿œµð×ü$ðÜü F4ð¨ü4,ùÑKöŒJhšBÐÿ÷œÿðrøðòùðþù ðü5 ð~üÿ÷¤ÿ ðøOôÉrI ð½ø ½ Fð‚üà翼X$µÿ÷Çÿ0¿ý翵ÿ÷‘ÿ@¿½¿µÿ÷‹ÿ@¿" ð}ü½è@" ðP¼µÿ÷ÿ" ðrü½è@" ðE¼¿µ$ FðSü F4ðcü4,öÑKöŒJhšBÐðøð›ù ð,ü5 ð)ü ðÜÿ ÿ÷Uÿ@¿½ Fð2ü FðCüæç¼pG¿pG¿pG¿pG¿pG¿2±FɲDø“BûÑpG¿xC!±ø+*úÑFpGøµ LF!h ++MI±K«B#`¿Kp¿#` ø½Oê8Fÿ÷×ÿ9Fîç¿ 8µFx8±%Fÿ÷Ûÿø(ùÑ`8½¿øµFxx±i±Fû«FD˜“ðøD ++ ÿ÷—ÿ…óˆ F°½è0@°pG¿T€$”$K`pG¿T-éðO$F‹F'F‘°®Feà(tÐÿ÷rÿ¶FvFø ë%(!FòÑ/òÑ;FOð :Fžø— ñ# u¼ñWòèßèðÿææææææ æ%.........ææææææææææææææææææææææææææææææPææææææææææUËæææÞË^æcæm|Žæ“Æ\ææ÷æú F°½èð ++ Þ#ô€iñÚÚ@ñé ñ#ðÓø ñ ô€oкñ¼¿IôyÊñ ++ ô€^#rFø0ŽF ñSF”FàfF³ûðòû3·Lã\Y±£ña ¼ñŒ¿Oð Oð £ë Û²´F ø;F*åÑ«óœ“ô€sqF“ ++кñЛ+ðï›+ðïôs“ðE›ð€ ñ“ð‹- Lÿ÷“þ›S±ºñЛ+ðù›+ð¹ñðM0xP±ÿ÷~þø 4(øѹñ?ôü®›+?ôø®š£ë ¹ñ÷ñ® ñÿ6>@Fÿ÷dþsùÑLDææ cçpxCð@.F÷æpxCô€s.Fòæÿ÷Qþ4ÕæñcÛø ñ (Àò¸px.FàæpxCô€c.FÛæpxCð€.FÖæpxCôc.FÑæôj@ðcpxOð0.FÈæ–ø ñ0 ©ñ0 (˜¿ôjò¹€.F ëŒ ëL øŸ¬ñ0 ©ñ0 (óÙHFºñ ¿eFbF•¦æ Cô€SçÛø ñ4ÿ÷ûý³FæpxCð.F“æ˜@ñ3#ðpxCð.F‰æÞñì€Ø@ñC"FÛøãÁé# ñ aæ Þæš*@ðCô€s Ûø #ô€i ñ ßæpxCð.FcæÛø ñ‘¹ñð&HF“’ÿ÷¬ýš›ÕB’FØF‚F™¡ë"êâvñÀñÿ;>± ñÿ;@Fÿ÷ý»ñÿ?÷ÑQFHFÿ÷Âý4DDÝø°æpxCð .F+æÞCô€iñ’€Ú@ñÓ€ ++ ñ#ðñ Óø æ@ñˆ€#ðCð,ç¥ëpFÿ÷˜ý'DïåHÿ÷„ýDÝæHF.FôjOç¿Ä$ô$ð€ AѸñ0Лƒ±š›+“ Ýñÿ9 ñÿ9@Fÿ÷Fý¹ñÿ?÷Ñ›D›+@ðÓ€›+±ºñÐOð ¦æ›ƒ±š›+“ Ýñÿ9 ñÿ9@Fÿ÷'ý¹ñÿ?÷Ñ›D0x(?ô¥­Oð šæÛø  ñ +æ›+?ô®ºñ?ô‹®}æ¸ñ0´ÑpæžëÔšéÔ^çÔ{Õ»ø  ñ æÛø0 ñ `{å ++ Ûø  ñ æpxCð.FˆåpxÛø .F ñ åHFQFÿ÷ ++ýñÿ9D>± ñÿ9@Fÿ÷Õü¹ñÿ?÷Ñ4DÝø°Tå#ô€søævx ñ0 ¦ñ0 (±Fö¥®0FbF.F]åpxCð.FXå›3“æ›3“ æž¹Ô˜·ÔZµÔOð ++*Õ»ù  ñ ·å™£ÔZ¡Ô'ÕÛø0 ñ €å ßøXÜæ0 4ÿ÷üæpxžƒð€vB–.F#å^õg¯›ø  ñ ’åZõ^¯›ø  ñ ‰åXõu¯Ûø0 ñ pðä!FOð Îåì$´µƒ°«Sø F“ÿ÷Úü°]øë°pG¿þç¿JKšB ÒÑCD H!ð1FDSøƒBBøùÑH IOðˆB¸¿@ø+úÛÿ÷Ç»¿Ä4*Àþç¿þç¿þç¿þç¿þç¿þç¿þç¿þ翵 ð6ú¹þç ½ñŠA¡õá`pGñŠ@ õáhpG#ABððX¿JB(¸¿0@€ñ`@“@õa@`pG#ABððX¿JB(úó¸¿0J@Bø 0pG€áà#ABððX¿JB(úó¸¿0J@Bø 0pG€âàJhCð`pGíàJhCð`pGíൠÿ÷Äÿ ðùûKh`½¿ ßDµ ÿ÷¶ÿÿ÷0úÿ÷8ú¨±ÿ÷áúFH¹ÿ÷ëú°¹ÿ÷Dú½è@ ÿ÷¿ ÿ÷0û½è@ ÿ÷‡¿ ÿ÷¶ú½è@ ÿ÷¿ Fÿ÷,û½è@ ÿ÷w¿¿µ! ÿ÷†ÿ½è@! 𹻿µ$ Fÿ÷{ÿ F4ÿ÷‹ÿ4,öÑKöŒ JhšBнè@ÿ÷º Fÿ÷hÿ Fÿ÷yÿ½è@ÿ÷ý¹¿¼µ# ÿ÷Zÿ½è@# 𻿵$ ÿ÷Pÿ½è@$ ðƒ»¿µ( ÿ÷Fÿ½è@( ðy»¿µ) ÿ÷<ÿ½è@) ðo»¿µ* ÿ÷2ÿ½è@* ðe»¿µ+ ÿ÷(ÿ½è@+ ð[»¿µ, ÿ÷ÿ½è@, ðQ»¿µ- ÿ÷ÿ½è@- ðG»¿µ. ÿ÷ ++ÿ½è@. ð=»¿µ/ ÿ÷ÿ½è@/ ð3»¿µ0 ÿ÷öþ½è@0 ð)»¿µ1 ÿ÷ìþ½è@1 𻿵2 ÿ÷âþ½è@2 𻿵3 ÿ÷Øþ½è@3 ð »¿µ4 ÿ÷Îþ½è@4 𻿵5 ÿ÷Äþÿ÷>ùÿ÷Fùˆ±ÿ÷ïù0¹ÿ÷Vù½è@5 ÿ÷¡¾ ÿ÷Bú½è@5 ÿ÷™¾ ÿ÷Èù½è@5 ÿ÷‘¾¿KhhhÛüÔpG¿KhhhÛüÕpG¿KhSø h#ð`pG¿KhSø hCð`pG¿KöDKh“BÐKöŒ“BÐpGKJ`pGKJ`pG¿¼)ˆ&"K`Z`š`Ú`aZapG¿ KöD Kh“B ÐKöŒ“BÐpG K H ++I ++J˜aÙabpGKH I J˜aÙabpG¿¼ `)())à)¨)˜) ++Jp´jëAëÁmhTø1›h-hÔÐPf`¥``p¼ pG¿ Kp´Ûi„ˆEyYk˜iÚiÄóÁŒ@Åó@$ê‘@hXh!CÅó€!ê‚@žhÜh ++CÅóÀi"ê @C1±[iÅó@ ê(Cp¼pG Jy‘ip´Êj hHhð”@Ãó€$êiMi‚@"CÃóÀŒh"ê¨@ÉhCÃó ê‹@Cp¼pG Kë@jëRø0 [h`pG¿ KjëÀChhðpG¿  ++Kj“è hhJ@’Ð pGÚh™h hhX@ð¿ pG¿ µDh‰ð¡üÿ÷Yý x˜!¿ðOô€0¿$ÿ÷Uý€ ÿ÷Xý€! Dÿ÷NýKh,нðSùð£ÿ Fð„ÿ½è@ ð¿¿œ8µ7K7JhFëƒëƒ›|Dh+YÑ(‰ðhüàˆÀóðû h.K@³ÀóOðÝú Fÿ÷.ÿF Fÿ÷Xÿ!ÿ÷ÿ!(Fÿ÷ ÿðùðùðÍý ðHÿðbÿ#xÛÕKx+³þçFöu ð¹úÚçð¢úKöDKh“BÐKöŒ“BêÑ ÿ÷]ÿ(åÑJ hCð`ÿ÷{þ ÿ÷bþ Kx+Ùѽè8@ ð¿ð›û¢çKh+ßÑÉç¿œþÿ¨¼ áD´8µ"K"JhFëƒëƒ›|Dh‹»(‰ðëû#xÛ(ÕàˆÀóð…ú hK@Ó±ÀóOð]ú Fÿ÷®þF Fÿ÷Øþ!ÿ÷þ!(Fÿ÷‹þðQý ðÌþ Kx[±þçFöu ðBúãçð+úÓçðFûÊç ½è8@𸾜þÿ¨8µ!K!JhFëƒëƒ›|Dhs»(‰ðû#xÛ%ÕàˆÀóð7ú hK@»±ÀóOðú Fÿ÷`þF Fÿ÷Šþ!ÿ÷Aþ!(Fÿ÷=þðý Kx[±þçFöu ð÷ùæçðàùÖçðûúÍç ½è8@ðm¾¿œþÿ¨8µKJhFëƒëƒ›|DhS»(‰ðQûàˆÀóðîù hK@˱ÀóOðÆù Fÿ÷þF Fÿ÷Aþ!ÿ÷øý!(Fÿ÷ôý ð7þ Kx±þç8½Föu ð¬ùäçð³úÑçœþÿ¨µCh؈Àóð¹ù½è@ ð¾8µF lhð ý(‰ð ûàˆÀóð¦ù Fÿ÷×ýF Fÿ÷þ!ÿ÷¸ý(F!ÿ÷´ý#yð+Ð ð„ÿ½è8@ ðí½¿pG¿pµFþ÷Jþ(EÐ(M)L+hëƒëƒÛh+;ИG0Fþ÷ÜþkhxÛÔðDùh‰ð«ú+hëƒëƒ›|C» ðCÿ$ Fÿ÷û F4ÿ÷­û4,öÑKöŒJhšBÑ Fÿ÷Žû Fÿ÷Ÿûþ÷_ÿðßø ÿ÷pû5 ÿ÷mû½èp@ ð¿þçðGú+hëƒëƒ£|+ÏÑË眼pG¿KöDKµh“B!ÐKöŒ“B!Ðÿ÷»ýF ÿ÷ý ÿ÷šý ðýð“ýð5üðAÿð+ÿ Fþ÷dþð ù½è@ ðo½Kh+ÝÐ ÿ÷¨ü ÿ÷‘üÖç¼´µÿ÷ýF ÿ÷oý ÿ÷lý ðSýð üðÿ Fþ÷:þðvù½è@ ðE½¿µÿ÷qýF ÿ÷Sý ÿ÷Pý ð7ýðíû Fþ÷ þ@¿½è@ðY¹¿µÿ÷YýF ÿ÷;ý ÿ÷8ýðÒþð8ý Fþ÷ þðEù½è@ ð½µð=ù½è@ ð ½µÿ÷9ýF ÿ÷ý ÿ÷ýðýð°þ Fþ÷éýð%ù ðöü½è@ 𠼿KFhAð€q`h›üÔpG$@ßDKFh!ð€q`h›üÕpG$@ßD"µK`Z`ÿ÷Eü½è@𠼿œ KHhIµJÃó4` `h JÃó#`ðHüðþýÿ÷4üðüû½è@ÿ÷¼áD¼´@áD¸J hCô3`pG¿páDJ h#ô3`pG¿páDJh C`pG¿páDOôqKJ`h C`pG¿ ßDßDJh#ôs`pGßD8µIKñˆt`d#h+,Ñch+/Ñ#j+2Ñ#i+5Ñci+8Ñ£i+;Ñ£h+>Ñãh+AÑãi+DÑKöŒ9M*hšBGУj+dÑ#k+]Ñãj+MÑKöŒ*hšBPÐ8½! ÿ÷óùch+ÏÐ( ÿ÷íù#j+ÌÐ3 ÿ÷çù#i+ÉÐ- ÿ÷áùci+ÆÐ. ÿ÷Ûù£i+ÃÐ/ ÿ÷Õù£h+ÀÐ* ÿ÷Ïùãh+½Ð, ÿ÷Éùãi+ºÐ2 ÿ÷ÃùKöŒM*hšB·Ñck+´Ð ÿ÷·ùOôqKJ`h C`¨ç0 ÿ÷«ùKöŒ*hšB®Ñ½è8@4 ÿ÷¡¹$ ÿ÷žùç# ÿ÷šù–ç¿D¼ ßDßD"8µ"K! `ÿ÷ù( ÿ÷šù) ÿ÷—ù* ÿ÷”ù+ ÿ÷‘ù, ÿ÷Žù- ÿ÷‹ù. ÿ÷ˆù/ ÿ÷…ù0 ÿ÷‚ù1 ÿ÷ù2 ÿ÷|ù3 ÿ÷yù# ÿ÷vù$ ÿ÷sùKöŒ M,hœBÐ8½ J h#ôs`ÿ÷dù+h£Bóѽè8@4 ÿ÷\¹D¼ßDµðÛùð%ùð½ù Kx ±ÿ÷ŠþðŒù ÿ÷Áú ðtú ðqú ðnú ðkú½è@ ðfº˜µ ðzú ðwú ðtú ðqú ðnú ÿ÷úðIù ð¼üðlù KxC¹ðùøKöDJhšBнÿ÷Vþóç½è@𛹿˜¼8µOöÿs˜BÐF ð¿üF ð•üõ ð?ûF ± F8½ ðœü F8½$ F8½¿ÿ÷à¿Kx±æpG¿˜Kx±æpG¿˜KöŒIð´hINMLH h6hK-h$hh‘B`^``Ü`aÑ I J hhYašað¼pG¿áD¼áD áD@áDDáDHHáDLáDøµÿ÷ËÿKh#¹ Kh;+ Ù J K O NMLIH:`2`+`#``ø½ JhCð€S`ëç¿´°ð?‹àÿ@áDDáDáDáD áD‹  ÿáD8µÿ÷•ÿMKLHIJ+`#`` `h+ Ð+Ð8½Oð`oðbIK``8½%Oðÿ0 JhCô€s`Dø<\Aø@ 8½¿@áDð?DáDHáDLáD°áD áD`áDKöDKh“BÐKöŒ“BÐpGÿ÷·¿ÿ÷¿¿¼KöDJð´h™BÐKöŒKHh]hLŸh`Þh%`iM‡`.`dhŠBÑšiXiIK``ð¼pGKh+àÑ Kh;+ÛØ I h#ð€S `Õ翼HáDáD@áDHáDLáD´°áD ! KF``hAð@`hðAð``h›üÕpG¿ áDKh+¿"KJK`pG° áDµ Kx¹½ ðFû#IJ h ‹@`½è@ðM»¿™¬”qàDµ Kx¹½ ð,û#IJ h ‹@`½è@ð3»¿™¬qàDKh+ÑJhCðC`pG°áDKh+ÑJh#ðC`pG°áD Jð´h,:Ð#hY7ÐPhÃëÃPø3PëÃ.hJh2C*`Pø3PJi.h2C*`Pø3`hÍh2h=C*C2`Pø3P ++i.h2C*`Pø3PŽi*h"ê*`Pø3 Íih#ê`KjŠj jC hBüÑTø?ZÈÑð¼pGd#Jðµh.@Ð3hY=жFUhÃëÃUø4 ëÄhÃi C`j‚j hBüÐUø4 ƒih C`jBj hBüÐUø4i ++h^ø?"ê ++`Uø4pÁh†h:h1C"ê:`Uø4Gi ++h"ê ++`Uø4@h ++h"ê ++`ZÃÑð½¿d KÀëÀZh´ëÁÔjë€ h ðAð!`k˜`h+üÑ]øKpGd ++KÀëÀZh뀛hëÁÐjð)`ÐpGkh+üÐpG¿dKÀëÀ[hëÀCkhÀ²pGd"Kš`Ú`aZašapGdKöD Kh“B ++ÐKöŒ“BÐpG K I ++JY``pG JK IhY`*ñÐJ`pG¿¼d' '´p%`%µ K„° ñËéLª#h+´¿ÃóAsÃóSëƒSø °½¿ü&@áDKöD Kh“B ÐKöŒ“BÐpGKH I JƒèpGKHI JƒèpG¿¼€d(<(4(Ø(¬(¤(K(hOðSø! h#ð ¿CðCð`pG¿€8µ F hJ ÐFà8¹(Fÿ÷áÿTøK÷Ñ8½8½ ûç¿KhSø 8±hð ñ°ú€ð@ pG€KhSø h#ðCð`pG¿€KhSø h#ðCð`pG¿€K Yh»ç€K Yhµç€K ™h¯ç€-éðOOð FFhJiKÒø€ßø°á³øÀfMgHgI¾øà(ð-ˆ‡°ˆ ˆ`úŒò£ø’úŽò’ª²sxø{’‚²’Š²Gê'’ÿ÷%ÿFHFÿ÷áþ-¸¿5/¿;F#­•ûóóëÓrRQñ€ÿ)@ó€ÿ!Oô‚r›;ñ€ÿ+@ó…€ÿ#%OôBOöÿwBH€BM€8+€ øˆ>KAI€€€²x*DÐœFHòkßøø ßøøŽFl09Oôzsà;PÐ ˆíúÔ®øpfxUªø`’²¦©ø 2Fí²ë¬ø°#D®øpøKšB€úÑ5Oôzrtà[Ô:Ð ˆ›²ðöÐOöÿrOðÿ0 K€°½èð®øpr]*ÄÑ ½ø PKI€J €½øPL€½øP%€½ø@€½ø0!ø„ÿ ½ŒBooted version 0x%x of CM3 PM Firmware. $¤$¬$´$¼$[%08x]%s: ERR WARN INFO DEBUG0123456789abcdefghijklmnopqrstuvwxyz(null)0x ++ ÿÿÿÿ ÿÿÿÿLàD(àDÐàDàD¸àDäàDààDÜàDdàD àD`àDàD,àDÿÿÿÿáD€  áDŒàDpàDœàDáD€  áD˜àDHàDTàDáD€  áD”àD4àD@àDˆàD àD,àDàD\àDhàDàDàD ++ ÿÿÿÿ ÿÿÿÿ8*ßD ßD0ßDh+ßD@+ßD(ŠßD ˆßD@ˆßD¨ˆßD ˆßD ŒßD ƒßDPˆßD8ßD ”ßDKÀ]¨aeÿÿÿÿáD€  áDà-ßDä-ßDì-ßDáD€  áD .ßD$.ßD,.ßDáD€  áD -ßD¤-ßD¬-ßD`-ßDd-ßDl-ßD -ßD$-ßD,-ßDÿÿÿÿ  ÿÿÿÿ)ßDƒßD“ßD’ßDßD‹ßDˆßDŠßDŒßDßD”ßD+ßDÿÿÿÿ   ++ ÿÿÿÿàDPàDDàD@àD àDàDàDàDàDHàD,àDàDàDßDßDßDßD  ++  ++ @ßD@ßDàDàD àD àD €€@GNUe‚‰â½geÛWÓ…;°¨q2W¸I…¸I…¬ ¥‰¬ ¥‰”ˆ¡ù”ˆ¡ù|=1|=1ÅpÕapÕaXq¡-dY‘€ ƒ ëÔ€üÿêÔƒüßêÔ…üßêÔ€üßêÔ…üßêÔ€üßlog_buf +\ No newline at end of file +diff -Naur --no-dereference a/firmware/am335x-pm-firmware.elf b/firmware/am335x-pm-firmware.elf +--- a/firmware/am335x-pm-firmware.elf 1969-12-31 19:00:00.000000000 -0500 ++++ b/firmware/am335x-pm-firmware.elf 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,388 @@ ++ELF(4M4 (4*4*4*ÀQåtd™ é í ñ õ ù ý   • • • • • • • • • • • • • • • • • É • • • • • • • • • • • • • • å • E Y ± • • • Å Ù í )=Qey¡µÉJh CôÉs`pG0áDð<¹KD›hpG¿ÊD8K D›`pG¿ÊD8KJh›²`pG,áDœKhZ* ØJëƒëƒ˜h0¿ pG pG¿œ#J$Khhð´#Mð"J/`"NÃóÀp!L"HÃó!JÃó€%7`ÃóÀ#p%pHhJh `Sh ÐHI€è0P`˜D냛hHð¼GiðÑI h)ИIÄë„dh±T`éçI˜ÄQø$@,öÑáç<áD8áD°™¬˜¨0áD4áDœ¸Oðÿ3´HLIJ#``]øK ``pG4áD0áD8áD<áDJh CôÉs`pG0áDJh›²Cê@`pG¿,áDJh#ðÿC`pG¿@áDKJhëƒëƒ|pG¿œKJhëƒëƒX|pG¿œµð×ü$ðÜü F4ð¨ü4,ùÑKöŒJhšBÐÿ÷œÿðrøðòùðþù ðü5 ð~üÿ÷¤ÿ ðøOôÉrI ð½ø ½ Fð‚üà翼X$µÿ÷Çÿ0¿ý翵ÿ÷‘ÿ@¿½¿µÿ÷‹ÿ@¿" ð}ü½è@" ðP¼µÿ÷ÿ" ðrü½è@" ðE¼¿µ$ FðSü F4ðcü4,öÑKöŒJhšBÐðøð›ù ð,ü5 ð)ü ðÜÿ ÿ÷Uÿ@¿½ Fð2ü FðCüæç¼pG¿pG¿pG¿pG¿pG¿2±FɲDø“BûÑpG¿xC!±ø+*úÑFpGøµ LF!h ++MI±K«B#`¿Kp¿#` ø½Oê8Fÿ÷×ÿ9Fîç¿ 8µFx8±%Fÿ÷Ûÿø(ùÑ`8½¿øµFxx±i±Fû«FD˜“ðøD ++ ÿ÷—ÿ…óˆ F°½è0@°pG¿T€$”$K`pG¿T-éðO$F‹F'F‘°®Feà(tÐÿ÷rÿ¶FvFø ë%(!FòÑ/òÑ;FOð :Fžø— ñ# u¼ñWòèßèðÿææææææ æ%.........ææææææææææææææææææææææææææææææPææææææææææUËæææÞË^æcæm|Žæ“Æ\ææ÷æú F°½èð ++ Þ#ô€iñÚÚ@ñé ñ#ðÓø ñ ô€oкñ¼¿IôyÊñ ++ ô€^#rFø0ŽF ñSF”FàfF³ûðòû3·Lã\Y±£ña ¼ñŒ¿Oð Oð £ë Û²´F ø;F*åÑ«óœ“ô€sqF“ ++кñЛ+ðï›+ðïôs“ðE›ð€ ñ“ð‹- Lÿ÷“þ›S±ºñЛ+ðù›+ð¹ñðM0xP±ÿ÷~þø 4(øѹñ?ôü®›+?ôø®š£ë ¹ñ÷ñ® ñÿ6>@Fÿ÷dþsùÑLDææ cçpxCð@.F÷æpxCô€s.Fòæÿ÷Qþ4ÕæñcÛø ñ (Àò¸px.FàæpxCô€c.FÛæpxCð€.FÖæpxCôc.FÑæôj@ðcpxOð0.FÈæ–ø ñ0 ©ñ0 (˜¿ôjò¹€.F ëŒ ëL øŸ¬ñ0 ©ñ0 (óÙHFºñ ¿eFbF•¦æ Cô€SçÛø ñ4ÿ÷ûý³FæpxCð.F“æ˜@ñ3#ðpxCð.F‰æÞñì€Ø@ñC"FÛøãÁé# ñ aæ Þæš*@ðCô€s Ûø #ô€i ñ ßæpxCð.FcæÛø ñ‘¹ñð&HF“’ÿ÷¬ýš›ÕB’FØF‚F™¡ë"êâvñÀñÿ;>± ñÿ;@Fÿ÷ý»ñÿ?÷ÑQFHFÿ÷Âý4DDÝø°æpxCð .F+æÞCô€iñ’€Ú@ñÓ€ ++ ñ#ðñ Óø æ@ñˆ€#ðCð,ç¥ëpFÿ÷˜ý'DïåHÿ÷„ýDÝæHF.FôjOç¿Ä$ô$ð€ AѸñ0Лƒ±š›+“ Ýñÿ9 ñÿ9@Fÿ÷Fý¹ñÿ?÷Ñ›D›+@ðÓ€›+±ºñÐOð ¦æ›ƒ±š›+“ Ýñÿ9 ñÿ9@Fÿ÷'ý¹ñÿ?÷Ñ›D0x(?ô¥­Oð šæÛø  ñ +æ›+?ô®ºñ?ô‹®}æ¸ñ0´ÑpæžëÔšéÔ^çÔ{Õ»ø  ñ æÛø0 ñ `{å ++ Ûø  ñ æpxCð.FˆåpxÛø .F ñ åHFQFÿ÷ ++ýñÿ9D>± ñÿ9@Fÿ÷Õü¹ñÿ?÷Ñ4DÝø°Tå#ô€søævx ñ0 ¦ñ0 (±Fö¥®0FbF.F]åpxCð.FXå›3“æ›3“ æž¹Ô˜·ÔZµÔOð ++*Õ»ù  ñ ·å™£ÔZ¡Ô'ÕÛø0 ñ €å ßøXÜæ0 4ÿ÷üæpxžƒð€vB–.F#å^õg¯›ø  ñ ’åZõ^¯›ø  ñ ‰åXõu¯Ûø0 ñ pðä!FOð Îåì$´µƒ°«Sø F“ÿ÷Úü°]øë°pG¿þç¿JKšB ÒÑCD H!ð1FDSøƒBBøùÑH IOðˆB¸¿@ø+úÛÿ÷Ç»¿Ä4*Àþç¿þç¿þç¿þç¿þç¿þç¿þç¿þ翵 ð6ú¹þç ½ñŠA¡õá`pGñŠ@ õáhpG#ABððX¿JB(¸¿0@€ñ`@“@õa@`pG#ABððX¿JB(úó¸¿0J@Bø 0pG€áà#ABððX¿JB(úó¸¿0J@Bø 0pG€âàJhCð`pGíàJhCð`pGíൠÿ÷Äÿ ðùûKh`½¿ ßDµ ÿ÷¶ÿÿ÷0úÿ÷8ú¨±ÿ÷áúFH¹ÿ÷ëú°¹ÿ÷Dú½è@ ÿ÷¿ ÿ÷0û½è@ ÿ÷‡¿ ÿ÷¶ú½è@ ÿ÷¿ Fÿ÷,û½è@ ÿ÷w¿¿µ! ÿ÷†ÿ½è@! 𹻿µ$ Fÿ÷{ÿ F4ÿ÷‹ÿ4,öÑKöŒ JhšBнè@ÿ÷º Fÿ÷hÿ Fÿ÷yÿ½è@ÿ÷ý¹¿¼µ# ÿ÷Zÿ½è@# 𻿵$ ÿ÷Pÿ½è@$ ðƒ»¿µ( ÿ÷Fÿ½è@( ðy»¿µ) ÿ÷<ÿ½è@) ðo»¿µ* ÿ÷2ÿ½è@* ðe»¿µ+ ÿ÷(ÿ½è@+ ð[»¿µ, ÿ÷ÿ½è@, ðQ»¿µ- ÿ÷ÿ½è@- ðG»¿µ. ÿ÷ ++ÿ½è@. ð=»¿µ/ ÿ÷ÿ½è@/ ð3»¿µ0 ÿ÷öþ½è@0 ð)»¿µ1 ÿ÷ìþ½è@1 𻿵2 ÿ÷âþ½è@2 𻿵3 ÿ÷Øþ½è@3 ð »¿µ4 ÿ÷Îþ½è@4 𻿵5 ÿ÷Äþÿ÷>ùÿ÷Fùˆ±ÿ÷ïù0¹ÿ÷Vù½è@5 ÿ÷¡¾ ÿ÷Bú½è@5 ÿ÷™¾ ÿ÷Èù½è@5 ÿ÷‘¾¿KhhhÛüÔpG¿KhhhÛüÕpG¿KhSø h#ð`pG¿KhSø hCð`pG¿KöDKh“BÐKöŒ“BÐpGKJ`pGKJ`pG¿¼)ˆ&"K`Z`š`Ú`aZapG¿ KöD Kh“B ÐKöŒ“BÐpG K H ++I ++J˜aÙabpGKH I J˜aÙabpG¿¼ `)())à)¨)˜) ++Jp´jëAëÁmhTø1›h-hÔÐPf`¥``p¼ pG¿ Kp´Ûi„ˆEyYk˜iÚiÄóÁŒ@Åó@$ê‘@hXh!CÅó€!ê‚@žhÜh ++CÅóÀi"ê @C1±[iÅó@ ê(Cp¼pG Jy‘ip´Êj hHhð”@Ãó€$êiMi‚@"CÃóÀŒh"ê¨@ÉhCÃó ê‹@Cp¼pG Kë@jëRø0 [h`pG¿ KjëÀChhðpG¿  ++Kj“è hhJ@’Ð pGÚh™h hhX@ð¿ pG¿ µDh‰ð¡üÿ÷Yý x˜!¿ðOô€0¿$ÿ÷Uý€ ÿ÷Xý€! Dÿ÷NýKh,нðSùð£ÿ Fð„ÿ½è@ ð¿¿œ8µ7K7JhFëƒëƒ›|Dh+YÑ(‰ðhüàˆÀóðû h.K@³ÀóOðÝú Fÿ÷.ÿF Fÿ÷Xÿ!ÿ÷ÿ!(Fÿ÷ ÿðùðùðÍý ðHÿðbÿ#xÛÕKx+³þçFöu ð¹úÚçð¢úKöDKh“BÐKöŒ“BêÑ ÿ÷]ÿ(åÑJ hCð`ÿ÷{þ ÿ÷bþ Kx+Ùѽè8@ ð¿ð›û¢çKh+ßÑÉç¿œþÿ¨¼ áD´8µ"K"JhFëƒëƒ›|Dh‹»(‰ðëû#xÛ(ÕàˆÀóð…ú hK@Ó±ÀóOð]ú Fÿ÷®þF Fÿ÷Øþ!ÿ÷þ!(Fÿ÷‹þðQý ðÌþ Kx[±þçFöu ðBúãçð+úÓçðFûÊç ½è8@𸾜þÿ¨8µ!K!JhFëƒëƒ›|Dhs»(‰ðû#xÛ%ÕàˆÀóð7ú hK@»±ÀóOðú Fÿ÷`þF Fÿ÷Šþ!ÿ÷Aþ!(Fÿ÷=þðý Kx[±þçFöu ð÷ùæçðàùÖçðûúÍç ½è8@ðm¾¿œþÿ¨8µKJhFëƒëƒ›|DhS»(‰ðQûàˆÀóðîù hK@˱ÀóOðÆù Fÿ÷þF Fÿ÷Aþ!ÿ÷øý!(Fÿ÷ôý ð7þ Kx±þç8½Föu ð¬ùäçð³úÑçœþÿ¨µCh؈Àóð¹ù½è@ ð¾8µF lhð ý(‰ð ûàˆÀóð¦ù Fÿ÷×ýF Fÿ÷þ!ÿ÷¸ý(F!ÿ÷´ý#yð+Ð ð„ÿ½è8@ ðí½¿pG¿pµFþ÷Jþ(EÐ(M)L+hëƒëƒÛh+;ИG0Fþ÷ÜþkhxÛÔðDùh‰ð«ú+hëƒëƒ›|C» ðCÿ$ Fÿ÷û F4ÿ÷­û4,öÑKöŒJhšBÑ Fÿ÷Žû Fÿ÷Ÿûþ÷_ÿðßø ÿ÷pû5 ÿ÷mû½èp@ ð¿þçðGú+hëƒëƒ£|+ÏÑË眼pG¿KöDKµh“B!ÐKöŒ“B!Ðÿ÷»ýF ÿ÷ý ÿ÷šý ðýð“ýð5üðAÿð+ÿ Fþ÷dþð ù½è@ ðo½Kh+ÝÐ ÿ÷¨ü ÿ÷‘üÖç¼´µÿ÷ýF ÿ÷oý ÿ÷lý ðSýð üðÿ Fþ÷:þðvù½è@ ðE½¿µÿ÷qýF ÿ÷Sý ÿ÷Pý ð7ýðíû Fþ÷ þ@¿½è@ðY¹¿µÿ÷YýF ÿ÷;ý ÿ÷8ýðÒþð8ý Fþ÷ þðEù½è@ ð½µð=ù½è@ ð ½µÿ÷9ýF ÿ÷ý ÿ÷ýðýð°þ Fþ÷éýð%ù ðöü½è@ 𠼿KFhAð€q`h›üÔpG$@ßDKFh!ð€q`h›üÕpG$@ßD"µK`Z`ÿ÷Eü½è@𠼿œ KHhIµJÃó4` `h JÃó#`ðHüðþýÿ÷4üðüû½è@ÿ÷¼áD¼´@áD¸J hCô3`pG¿páDJ h#ô3`pG¿páDJh C`pG¿páDOôqKJ`h C`pG¿ ßDßDJh#ôs`pGßD8µIKñˆt`d#h+,Ñch+/Ñ#j+2Ñ#i+5Ñci+8Ñ£i+;Ñ£h+>Ñãh+AÑãi+DÑKöŒ9M*hšBGУj+dÑ#k+]Ñãj+MÑKöŒ*hšBPÐ8½! ÿ÷óùch+ÏÐ( ÿ÷íù#j+ÌÐ3 ÿ÷çù#i+ÉÐ- ÿ÷áùci+ÆÐ. ÿ÷Ûù£i+ÃÐ/ ÿ÷Õù£h+ÀÐ* ÿ÷Ïùãh+½Ð, ÿ÷Éùãi+ºÐ2 ÿ÷ÃùKöŒM*hšB·Ñck+´Ð ÿ÷·ùOôqKJ`h C`¨ç0 ÿ÷«ùKöŒ*hšB®Ñ½è8@4 ÿ÷¡¹$ ÿ÷žùç# ÿ÷šù–ç¿D¼ ßDßD"8µ"K! `ÿ÷ù( ÿ÷šù) ÿ÷—ù* ÿ÷”ù+ ÿ÷‘ù, ÿ÷Žù- ÿ÷‹ù. ÿ÷ˆù/ ÿ÷…ù0 ÿ÷‚ù1 ÿ÷ù2 ÿ÷|ù3 ÿ÷yù# ÿ÷vù$ ÿ÷sùKöŒ M,hœBÐ8½ J h#ôs`ÿ÷dù+h£Bóѽè8@4 ÿ÷\¹D¼ßDµðÛùð%ùð½ù Kx ±ÿ÷ŠþðŒù ÿ÷Áú ðtú ðqú ðnú ðkú½è@ ðfº˜µ ðzú ðwú ðtú ðqú ðnú ÿ÷úðIù ð¼üðlù KxC¹ðùøKöDJhšBнÿ÷Vþóç½è@𛹿˜¼8µOöÿs˜BÐF ð¿üF ð•üõ ð?ûF ± F8½ ðœü F8½$ F8½¿ÿ÷à¿Kx±æpG¿˜Kx±æpG¿˜KöŒIð´hINMLH h6hK-h$hh‘B`^``Ü`aÑ I J hhYašað¼pG¿áD¼áD áD@áDDáDHHáDLáDøµÿ÷ËÿKh#¹ Kh;+ Ù J K O NMLIH:`2`+`#``ø½ JhCð€S`ëç¿´°ð?‹àÿ@áDDáDáDáD áD‹  ÿáD8µÿ÷•ÿMKLHIJ+`#`` `h+ Ð+Ð8½Oð`oðbIK``8½%Oðÿ0 JhCô€s`Dø<\Aø@ 8½¿@áDð?DáDHáDLáD°áD áD`áDKöDKh“BÐKöŒ“BÐpGÿ÷·¿ÿ÷¿¿¼KöDJð´h™BÐKöŒKHh]hLŸh`Þh%`iM‡`.`dhŠBÑšiXiIK``ð¼pGKh+àÑ Kh;+ÛØ I h#ð€S `Õ翼HáDáD@áDHáDLáD´°áD ! KF``hAð@`hðAð``h›üÕpG¿ áDKh+¿"KJK`pG° áDµ Kx¹½ ðFû#IJ h ‹@`½è@ðM»¿™¬”qàDµ Kx¹½ ð,û#IJ h ‹@`½è@ð3»¿™¬qàDKh+ÑJhCðC`pG°áDKh+ÑJh#ðC`pG°áD Jð´h,:Ð#hY7ÐPhÃëÃPø3PëÃ.hJh2C*`Pø3PJi.h2C*`Pø3`hÍh2h=C*C2`Pø3P ++i.h2C*`Pø3PŽi*h"ê*`Pø3 Íih#ê`KjŠj jC hBüÑTø?ZÈÑð¼pGd#Jðµh.@Ð3hY=жFUhÃëÃUø4 ëÄhÃi C`j‚j hBüÐUø4 ƒih C`jBj hBüÐUø4i ++h^ø?"ê ++`Uø4pÁh†h:h1C"ê:`Uø4Gi ++h"ê ++`Uø4@h ++h"ê ++`ZÃÑð½¿d KÀëÀZh´ëÁÔjë€ h ðAð!`k˜`h+üÑ]øKpGd ++KÀëÀZh뀛hëÁÐjð)`ÐpGkh+üÐpG¿dKÀëÀ[hëÀCkhÀ²pGd"Kš`Ú`aZašapGdKöD Kh“B ++ÐKöŒ“BÐpG K I ++JY``pG JK IhY`*ñÐJ`pG¿¼d' '´p%`%µ K„° ñËéLª#h+´¿ÃóAsÃóSëƒSø °½¿ü&@áDKöD Kh“B ÐKöŒ“BÐpGKH I JƒèpGKHI JƒèpG¿¼€d(<(4(Ø(¬(¤(K(hOðSø! h#ð ¿CðCð`pG¿€8µ F hJ ÐFà8¹(Fÿ÷áÿTøK÷Ñ8½8½ ûç¿KhSø 8±hð ñ°ú€ð@ pG€KhSø h#ðCð`pG¿€KhSø h#ðCð`pG¿€K Yh»ç€K Yhµç€K ™h¯ç€-éðOOð FFhJiKÒø€ßø°á³øÀfMgHgI¾øà(ð-ˆ‡°ˆ ˆ`úŒò£ø’úŽò’ª²sxø{’‚²’Š²Gê'’ÿ÷%ÿFHFÿ÷áþ-¸¿5/¿;F#­•ûóóëÓrRQñ€ÿ)@ó€ÿ!Oô‚r›;ñ€ÿ+@ó…€ÿ#%OôBOöÿwBH€BM€8+€ øˆ>KAI€€€²x*DÐœFHòkßøø ßøøŽFl09Oôzsà;PÐ ˆíúÔ®øpfxUªø`’²¦©ø 2Fí²ë¬ø°#D®øpøKšB€úÑ5Oôzrtà[Ô:Ð ˆ›²ðöÐOöÿrOðÿ0 K€°½èð®øpr]*ÄÑ ½ø PKI€J €½øPL€½øP%€½ø@€½ø0!ø„ÿ ½ŒBooted version 0x%x of CM3 PM Firmware. $¤$¬$´$¼$[%08x]%s: ERR WARN INFO DEBUG0123456789abcdefghijklmnopqrstuvwxyz(null)0x ++ ÿÿÿÿ ÿÿÿÿLàD(àDÐàDàD¸àDäàDààDÜàDdàD àD`àDàD,àDÿÿÿÿáD€  áDŒàDpàDœàDáD€  áD˜àDHàDTàDáD€  áD”àD4àD@àDˆàD àD,àDàD\àDhàDàDàD ++ ÿÿÿÿ ÿÿÿÿ8*ßD ßD0ßDh+ßD@+ßD(ŠßD ˆßD@ˆßD¨ˆßD ˆßD ŒßD ƒßDPˆßD8ßD ”ßDKÀ]¨aeÿÿÿÿáD€  áDà-ßDä-ßDì-ßDáD€  áD .ßD$.ßD,.ßDáD€  áD -ßD¤-ßD¬-ßD`-ßDd-ßDl-ßD -ßD$-ßD,-ßDÿÿÿÿ  ÿÿÿÿ)ßDƒßD“ßD’ßDßD‹ßDˆßDŠßDŒßDßD”ßD+ßDÿÿÿÿ   ++ ÿÿÿÿàDPàDDàD@àD àDàDàDàDàDHàD,àDàDàDßDßDßDßD  ++  ++ @ßD@ßDàDàD àD àD €€@GNUe‚‰â½geÛWÓ…;°¨q2W¸I…¸I…¬ ¥‰¬ ¥‰”ˆ¡ù”ˆ¡ù|=1|=1ÅpÕapÕaXq¡-dY‘€ ƒ ëÔ€üÿêÔƒüßêÔ…üßêÔ€üßêÔ…üßêÔ€üßlog_bufŠ‡ ö‡Üá0*PP%`GP9Î! Æolz¯…@5 ] N  [xSíMêÕNP QçúRPgSPCVPÿXPYPÍZPO[P`\P¦^P)_P0`PzaPßbPecPìePTjP p ++³qP ++crP H m6 nê rtcoÎ rawsç vs ++EwW ++4xs ++Cyy ++–zy ++ß}á ++~s ++Ìs ++£€ò ++Mù ++¸‚% ++íƒ% ++h„%ìì6áøš‡Preg‡QEïPreg®×]ïÙP”œâ4ìPE!QÿÛ½"$Þ9'.;`$,œ4$ìN0‚ ÿ0œ-o "@œO!.P!9Q"0•Pœ~#ÿP˜$õŸ%d,œ"©ÄœZ%id«Z¤³¬Pc­Pj®Pq¯P&ÿ±ÿÑ&ÿ’0¶'&ÿ´H½1'&ÿÄ`¾J'(ò)Pœ*int"½ÏT,œ &"TxÑœ9å.ù&"Z˜ÒÂ9."&"^°Óè97.K#"`ÈÔ9`.t E€œe+QSÿ€ÛB‰"ŒÞ9.±"€á”œØæáZÄ,ïãPåÿ”åµ"ž ++è9.+"먜KjëZ>,ïíP_ÿ¨ï(}"² ++ò9‘.¥$°ú%¼œ$åÿ%Øœ-A.§7P/X6œ0€²1²~/q)¢/öZ°/Ô%™/Z¬/º%˜/Â%¨.Ç.‰.0.O.x.L.Ö.9.42jjFÀ‡ ‡àU*`J£intÿØ0aHm3,VÑ·verhnum hT!·Ÿ"ÎhÇ Ç~hÝ ++Ç%«&h4'V ++ÇÀ,*Mda+hlen,hT-h .M V] ÇÍD1š»2zŸ4š*5Ýà6hª Ç ÍHôlœ‘ iH¸ úÐ ÛæöPt ñ ü $ (.-PO4AP5 8(>3]P0J>€P3QX$R ++’TæPt­GH` ++œ´ fªv5,÷9]Ĉˆ+àà,²²)½½’}}²²9¨¨:88(®®‘ÃÖ– ++ é‡ ú‡l–·*`ê±±UJáe“€;0¬ · ++‰ ž  $×intÃÐæ± ¸l ++œþ ++Äî rÖ PóP óxœu汸zP ++Ä0 ~Ö PóP†ád P"ì P" Â&œÓæ&±Q–Ö® PóPœá P"¦ì P" j/¨Xœºi1±r¸ä ++N! ++Ä´ êÖ P0²÷5 PtºáI PtÎÒ Øìn POÞì‚ P5ä• P;ô÷© Pt úá PtïRœv5,€€œqq*88(²²)}}²²9¥¥(91‡ ‡z2!%œßf‡ O‡ø¾H0[g‹œ‹s‹PcÈn%écs”  int ++šQ` %(œ×s ×'ret %R ++Ý šbý‡ ‚‡<†H0[n ~<<œ~c ~‚f\PwRuwint¬~xœÆstrƶ ™Æá ++†> ÓQ ̦~”.œ(strÆ Ÿ%s ™Æ  ++®>±9 ?H‘?v?gg¯Ü‡ ؇Äx“[–íÄlœílvlí¾fmtô‘t¼%øretí  ap‘d ++ø‘ P”$ Qt R óP2$€$" ++œÝ P‘\ Q‘` § P: intQú  )0 œBlvl)íPÌíT÷íôtt~茀$dœœïïnno‡ Q ‡<V[á>*^^%`1 R——padRžqR— retT— ++intQ BÿÿL BÿnumB^»B—n B C3 pEÿ cEž ž — ïZ—<8œ‡ fmtZ‡) apZ’–L `«‘´pa‡´‚ a‡chb—nb—& ++numc^} ++»d—+ tmpd—ï h d—£ g e—Ñ b fž¬9 g3Îreth—¼i%¶Š y%  ++* > ÷J“ j¥‚R ’áÿÖ4ËLÀaµ ‚RìÏõJehAÔ€]uh‹tFPxeò䀓uò‹ FPxe¢ ,W€Éu¢ ‹° FPxeà 9™€ÿuà ‹î FPxe€ ++çÖ€5u‹’ ++FPx XF!FóP- @F šF FF!ÐQ"Py! \<PyQz d \!p g\Pô$!€ ++\vPyQz" FP0 "ž#©$ ©%&ž»'» ~(œQ—t œ )fmtQ‡‘p*+apS’‘d+retT—Pˆ P‘PQ‘T&0'»$s ;AÄ$" ,nn,``,¦¦,¬¬áO ++‡ ¨ ‡” L÷*`š È” œc§˜ Hœ}Á ©}`Ò ©}Ò Ù, ç , È , ò , þ , ++Æ¿ ¿E~  Ú \¯­­ª" ‡  ++‡è N  ++è œ^ ++ì œL ++ð œ; ++ ô œ ++&ø œ ++,ü œp ++2 œ, ++8 œCQ ‡ p ‡ (¨*`… °°¬ ++Q Ý ++ 9 í ++[ ¦ Ç ++ø ++  ++Ž  À f . Ñ ++$ int¯ ° œà ; P> ++C  œ val,P reg°‹º ++ ,$ œ; reg °À ™ ™ .5 ‡ Þ ‡0 ˜ 80 (œfÏ fó f$þ mSint`²X (œµÏ fMó fnþ mSq&€ (œöÏ &f—ó (f¸þ )mSˆ1¨ œÖ 3mSà;¸ œÖ =mS»£ ‡ ‡È Fj *`ø È œ= RÐ :oP@Ö EP@int( 'ä ^œ^ì :®PO ð P ô [ ú f  q  | ++ ‡îPO ’P2 ++" ‡PO( 'P1 ++2 ‡:PO8 ¨NPt B ‡POJ CD œ˜L :‡P! V EP![ JX Dœ iLáb :ÎPtj ³âPt ‚ |ˆ :ÿPtŽ ³Pt – |l ]œ œW¤ :FP# ® EP#} d° œ‘¸ :€P$  EP$g kÄ œËÌ :ºP( Ö EP(x rØ œà :ôP) ê EP)‰ yì œ?ô :.P* þ EP* €œy:hP+ EP+ ‡œ³:¢P, &EP,9 Ž(œí0:ÜP- :EP-V •<œ'D:P. NEP.E œPœaX:PP/ bEP/, £dœ›l:ŠP0 vEP0Ö ªxœÕ€:ÄP1 ŠEP1£ ±Œœ”:þP2 žEP2´ ¸ œI¨:8P3 ²EP3Å ¿´œƒ¼:rP4 ÆEP4ç ÆÈFœ/Ð:¬P5 ÔP Ø[ Þf ä| ++î‡äP5ô’÷P2 ++þ‡ P5P1 ‡P5v5,²²)Ž Ž 00—õõ˜°°™ååš›88(ó󀀜ÂÂqq*Q‚ ‡ Ç ‡š ++ HHÿ Ý `§ œqid%P'!$œ“id!%Pš '8œÂid'%Pval)HSç 1Pœñid1%Pval3HSö ;h8œ  ++ H v5H 4 ? ) · O ))I‡ y‡9 *`ꢢUJáe“€;0¬ · ++‰ ž  $×intÀ¹¹~ $ ++PÖ$% ©ëë¹ + ++8!% Ûë¹ ++^)'ø$ ÿ¼‡ ñ‡ ¨ *` Q0úR,gS,CV,ÿX,Y,ÍZ,O[,`\,¦^,)_,0`,za,ßb,ec,ìe,Tj,C,T§ŽŸ0"ñ•#,ç$,ý%,«&, Ë',¿(,),ÿ*,’+, #,,$m-,(ñ.,,÷81¦¼2,3,<4,45, L6,`7,,8,®9,:, ÿ;,$’<,(#=,,m>,0ñ?,4–B˘C,qD,o üá,º,‡,,. var, ++‰, ++),Em,S valm, vm,Rg,x valg, vg,Ìa, vala, va,å[, val[, v[,Ît,ç valt, vt,¤U,  valU, vU,ÙO,1 valO, vO,TI,V valI, vI,\z,{ valz, vz,.¤¬¬ pd¤7 À¦, t§, int 1( œ C2¸Xœ‚?,0œ val?,.pd?7M€,@\œî4€înv‚,Â@ „cÝÒSJ8‡¬nc£üJPi"Ñ  .zhˆI> ü†p"B 3Ê,œHœL4îUv,vVœ€‘qvfŠ ™äœnpd™7Pž,œ–pdž7¯l²¬0œ$ à´¬{¶ó‹Ð•ä ÷{.º‹.•S  ++¢58; TúQ<W ñm@s ¦!ˈ"ˆ~Â!x #v5,#;#¢W!sÌ$#× Á#²;# W#xý Á|²‡ =‡È *`”ffäIJ¼€int£8"Ï$÷$Y $˜!$ í"$Ç#$1$$'%$­'$ „($$ )$(+$,y,$0‰-$4 92 ++2~ m œOp% " dd ++2 + eOz`% TvC‡ ͇  @@ÿ Ý `^WW~@tˆ&G¢‡ ì‡HŽj á 0*`G79µ! Æolz¯…@5 ] N  [xSíMÑÕN7 QÎúR7gS7CV7ÿX7Y7ÍZ7O[7`\7¦^7)_70`7za7ßb7ec7ìe7Tj7pï ³q7 cr7 ++H m nÑ rtcoµ rawsÎ vZ Ew> 4xZ Cy` –z` ++ ïß}È ~Z ÌZ £€Ù Mà ¸‚% íƒ% h„%ÓÓ  È ß… cc¬ ++Q Ý ++ 9 í ++[ ¦ Ç ++ø ++  ++Ž  À f . Ñ ++$ intêcáUJáe“€;0¬ · ++‰ ž  $×C7þ§Ž”c9äIJ¼€ 7\ÿ Ý Ý!H\œ)4!Óâ#)>$7QRV"n-ËP@<$Q˜t8ßP€|-óQ€ŠCŽN”YPtžYP? µºP¤üœ©4PÓlâR©Õ‰S7óDT7'ØUc:ÄÎdÞoäz¾Ptì…ÒPtòåQ0úþPuQ1þ›C¦ Y,P1N&oJP ++uj,±F¼fP1ZÇyP0`ÒŒP0rYŸP?vÝ Ñ™ œœÂ4™Ó\⛩·‰œ7ÊD7ó¾ÎdÞoäz/Ptì…CPtòVQ0úoPuQ1þ¦Y‹P1o P ++uj± Ý,YP?KË<˜œÂ4ËÓâÍ©a‰Î7tDÏ7Zjdzo€zBPtˆ…VPtŽiQ0–‚PuQ1š¦ªo P ++uj°±¶ÝÂYP?kõÔ„œ² 4õÓ°â÷©TDø7ý‰ù7òüd oz@ Pt…T Pt g Q0(€ PuQ1.Y“ P1@o¨ P ++ujFÝüXœ ++4Ó.â©OfdpYP1ŒpRœó ++4Órâ!©ž‰"7±D#7Ï|èj ++P3‚Œd’z ++Ptš…¤ ++Pt · ++Q0¨Ð ++PuQ1¸óã ++P5ÂYP1¤;Äœ 4;ÓP Ž Aȼœ4 hAcâ!iCcÐþð i Pvü*Ž P15¢ Pt&@¶ Pt<5Ê PtB@Þ PtFKJVPa POVa P5`** P;fl"$}„œÙˆˆpœ% àŠc[¢wª‚ˆ P1°‚› P0¶® P?º˜¾£Â®Æ¹ÌÄæ PtÐÏÚ P1èÚ P0#îåP0‰®ø6œÌ à°cyþw‚g P1 ‚z P0 P?£¹ ij Pt$Ï.P1èÊ0.œ[àÌc—6w>‚P1D‚!P0J4P?N£TÄQPt$^Ïä`0œïàæcµfwn‚P1t‚°P0x¹|ð‚ÄÖPt†ÏP1,úœ–Ï P1 6œÅàcÓ¦w®‚`P1´‚sP0¸˜¼¹ÂÄ™PtÆÏ̵P1ÖûP3%ÊÐ&%'v57'¸67'X‡(g)'qˆö'Â%*wwF*¯ ¯ G*C C I*º ++º ++ H*íí,*¢¢+*WW)*//@*]]?*N*ÊÊO*‚‚J*88-*ºº0*QQ<*L*ç ç *''*''C*~~3*––)*õõ˜**ÀÀ=*FFG*¥¥(*²² ++)*qq ++**}} *²²9*88 ++(*¯¯D*llQ*  K***ÌÌ,*ZZ1*  +*ïï.*€€œ*vvA*š š *§ § *-*ÙÙ4ì ó‡ ‡Øàªá 0*P P%`êÎÎUJáe“€;0¬ · ++‰ ž  $×int”ÎäIJ¼€ P3ÿ Ý GP9ª! Æolz¯…@5 ] N  [xS íMÆ ++ÕNP  Qà ++úRP ++gSP ++CVP ++ÿXP ++YP ++ÍZP ++O[P ++`\P ++¦^P ++)_P ++0`P ++zaP ++ßbP ++ecP ++ìeP ++TjP pä ³qP crP H m nÆrtcoªrawsà  vO Ew3 4xO CyU –zU ++äPŽvarP‰P)P~u¦= wÎ&¾= ƒÎAAØØCÎWOòØQξ؜ËñØðœ,å²;œTÜ ç ¨D$Lœ¦varFP;Hò Lý P T \ QVÎpœøvXPY\vZ ‚l wl lYÀa΄œJvcP‚\Še ‚• w© l‚]l˜œ§!ùlοvnPà\œp ‚ó w làŽ¬œÄš¦Èœá²//‘Ø8œ@!ì‘ÎS"ŽÂ³,#šœ$J) @%P!$V) T%P($b) h%P3$n) |%P-$z) %P.$†) ¤%P/$’) ¸%P*$ž) Ì%P,$ª) à%P2$Â) ó%P@$Ú) %P0&î) %P4$ô) /%P$'ü) %P#vÎœœÈ(¦€˜éx)˜²¯$4 Œ%P!$$4  %P($*4 ´%P)$04 È%P*$64 Ü%P+$<4 ð%P,$B4 %P-$H4 %P.$N4 ,%P/$T4 @%P0$Z4 T%P1$`4 h%P2$f4 |%P3$l4 %P#$r4 ¤%P$$4 ·%P@* 4 %P4'ó¬Hœœ "¾º ++û #º +++ËÄò²? ¶J ºU È` $Îk @ %P1$Ôv S %P4$Úv f %P2$àv y %P1$æv Œ %P0*ðv %P3,¯ôdœ… ++-Ø(°Û )°+åD$ü î %P3$  ++%P0$  ++%P1$ ' ++%P2$ : ++%P4$Œ M ++%P1— $$¢ i ++%P1(­ 2¸ Nà .F1ÎX:œ1 /–1UÓ0n31 1ret4Î )È2«7%N$jÎ ÷ ++%P4$r¢ ++ %P4$zÙ %Pt€€ 'ˆä %P47 H¾˜œ` +Ë òبœ‚ +å°3è4PD4v6P¼4¸7P´4§8P¸5X‡5ºŽ%611G6ss86××(6ÃÃ'6CCH6ˆˆ96ö ö 688 (6²² )6(( ++6’’ ++6 ++6·· ++6ç ç 6~~36ÙÙ46š š 666 ++6¥¥(6ÎÎ ++6 ++ ++ ++6 ++6ll*6¡¡ 6––)‡ L‡*`ꢢUJáe“€;0¬ · ++‰ ž  $×intÀ¹¹~ $ ++iÖÀ& ©ëë¹ + ++w#¨& Û ++1,& ÛnŽ‡ Ò‡¸èäá0*PP%`êÎÎUJáe“€;0¬ · ++‰ ž  $×int "= ++:#= ++¥$= ++è%= ++¸'= ++(= ++F)= ++Å*=[ ô/ Zd var\PD¸dœ$>lœŸvar?PS"DLˆxœØXÀ@ÎXaŽD’z$œLs ++‚$Œœ#var„PS6°0œHvarŸPt·¶à œÎ¾4œ‘[P3&fP3Ê44œÉD[¹P3ZfP3(×hœîvarÙP’æ„œvarèP¥±-ÜHv5P¸6Pö‹ÎÔŒ%Î¥¥(––)ÚD‡ º‡ 8;*`”nnäIJ¼€int£8*Ï,÷,Y ,˜!, í",Ç#,1$,'%,­', „(,$ ),(+,,y,,0‰-,4 a!M ++Ñ!3 var#, ºv ˆœœ ixn¸*²f{6̲fAß SJ¿ ++ÑJ3 varL, Z(”œ ++ inX œ<à„¨l à³ ~‡¼4œ/ч3¾ Ù‘ð0œTÑ‘3ß ˆš, œŒÑš3! valœ,!! s¥8œ¯ i§n9!ˆ­LTœÜº, 8œ÷¯¼‘hÖ½n‰!~n÷£)h/upEdK3,`•Plv5,¸6,/’œ‡K­e¸¢žÈ‡qØ¢|܇ ð‡U*`”ffäIJ¼€int£8"Ï$÷$Y $˜!$ í"$Ç#$1$$'%$­'$ „($$ )$(+$,y,$0‰-$4 92 ++2~ m žO' " dd ++2 + qOz ' T0m‡ ‡§`*íMGÕN QDúRgSCVÿXYÍZO[`\¦^)_0`zaßbecìeTjpe³qcrH m“ nG rtco+ rawsD ++Çe¸ ++‰nep ++0e¬ ++O-e  ++x@e” ++LQeˆ ++Öae| ++9~ed ++4‡eX‡ º‡Ø üá0*PP%`… ÔÔ¬ ++Q Ý ++ 9 í ++[ ¦ Ç ++ø ++  ++Ž  À f . Ñ ++$ int P  ++varP ‰P )P V,0 ++reg,Ô var.P î5S ++reg5Ô var7P…>Ôy ÿ>Ô ++id>W×ØTœS, (œUc¾!nQøcn 6 A6 $ß!Û< ++1öëß!0F C<F GSÛF :öëqHÔT &œ¹ÿHÔò!idsH¹B"retJÔy"iKÔÆ"j SPu ¿!W"™ Q%| œûidQWæ"varSP##W^œ œt$id^WP   `6#  $S#Û¦ 1f#öz#ëS##c¸ œí$idcWP0¼ e<Ž#¼ G«#Û :¾#öÒ#ë«##¢hÔ œ%Ü UP1#Ìmà œ7%è UP2#rì œ\%ô UP2&³m€ s!P&­¹„&3¹ˆ'v5P(s°)'˜»!¥(¿Ë)'¦Ö!À',æ!À'cö!¥'B!À'Ø!À/9‡ ü‡*`… ¨¨¬ ++Q Ý ++ 9 í ++[ ¦ Ç ++ø ++  ++Ž  À f . Ñ ++$ intÆ¿¿~ $ ++cÜd( ¯ññ¿ + ++B!<( áñ¿ ++Ø/-4( /¬‡ ‡z*`… ¨¨¬ ++Q Ý ++ 9 í ++[ ¦ Ç ++ø ++  ++Ž  À f . Ñ ++$ intÆ¿¿~ $ ++˜ÜØ( ¯ññ¿ ++ + ++¦!¬( áñ¿ ++,0-¤( ‡ B‡ÚC::§Ž`Ÿ0"Þ•#:ç$:ý%:«&: Ë':¿(:):ÿ*:’+: #,:$m-:(ñ.:,÷81“¼2:3:<4:45: L6:`7:,8:®9::: ÿ;:$’<:(#=:,m>:0ñ?:4–B¸˜C:qD:²É`)A #ß()Þ ûô ++ô~“x4)ä䜇 é‡ø Ô:*`”nnäIJ¼€into,˜val,˜reg,n 1˜»reg1n ++D6 }=nè ret?n i@n ¿Nn retPn iQn ÛT˜3bÑbn ÿdn ™en ©fn àgn sclhn %in jn¡nø Ôœ¸¶¸æ#len‘¾o$Ñ’˜Ž$e“ÊX *”˜ •˜  –˜ —˜ ˜˜uü ¦'ŒŸ!0œD¯¬$Ÿ !Xa¯Á$Ÿ!xž~¯Ö$Ÿ! Ÿ›¯ë$Ÿ!À ¸¯%R!è«š&%è1?%<G]%Rp%]Ž%h¬%sâ%uš!Š;Œ?&T&u¨!0‹]Œh&u®!ŒŒ}&V!Ñ^!ÜPyuœ!H®ÀŒ’&§&u !h±æŒ½&Ò&»´!ˆ²u´!ˆ9Œç&ü&uÂ! ÀBŒ'&'uÈ!¸º`ŒuÌ!н~ŒÃÐ!è¶õèÓ<'Þ]'»Ð!IÞuÐ!9Œ©'Ë'ŸÔ!@C¯uÒ!XÇŒí'(»"ÃQu"9Œ<(Q(è"pÉ×pøf(‡( £! Ÿ&"U¯Ó(»0"¨^u0"¨9Œè( ++)uL"ÈÎýŒ,)A)uN"èÑ#ŒU)j)uX"ÒIŒ~)“)u`"(ÓoŒ§)¼)uj"Ô•ŒÐ)å)up"ÕŒù)*"ÅH#¾[$ÜÜ;$ˆˆ6vi!‡ P‡p @@ÿ Ý `^WW~@· t)G È!‡ }‡Ì"ŒÀá0*`êµµUJáe“€;0¬ · ++‰ ž  $×int•9Ý reg9µ ++i;µ¤/þ reg/µ ++i1µ kC% regCµ ²HµÌ"|œ» ÿHµ"*idsH»\*iJµ•*¼Þ"NŽÈË*Þ"Óä*Ý#Ré7+#ôQ+Á>ÃH#Tœ¥Wœ#$œ!idW>PÝœ#@Yé¤+@ôÁ+–\À#(œkid\>P¼À#`^È,`Ó1,la%è# œ¬ida>„,þì#c¥,8kµ$œÕ$P0ïsµ$œþ($P2í{µ0$œ'<$P0 ‚µD$œPP$P2IaŒg7?»e»” v57!g¤" P¯™!Á¿" 8Ê´ ^Ú´ iê™ wú´ 1 ++´ª#‡ ƇÃC::§Ž`Ÿ0"Þ•#:ç$:ý%:«&: Ë':¿(:):ÿ*:’+: #,:$m-:(ñ.:,÷81“¼2:3:<4:45: L6:`7:,8:®9::: ÿ;:$’<:(#=:,m>:0ñ?:4–B¸˜C:qD:Éà)A¢#ߨ)Þ ûô ++ô~“2˜)ä% : ; I$ >  I: ; (  I: ;  : ;  : ; I 8  : ;  ++ : ; I8  : ;  : ; I : ; I I'I'.?: ; 'I : ; I.?: ; ' : ; I4: ; I.: ; '@—B: ; I1X Y  411X Y 1: ; I‰‚•B1 .1@—B!1".?: ; '@—B#1RUX Y $.?: ; 'I@—B%4: ; I&1RUX Y '1(‰‚•B)Š‚‘B*$ > +41,4: ; I-4: ; I.4: ; I?</4: ; I?0I1!I/ 2.?<n: ; % U$ > $ > : ; I : ;  : ; I8  : ; I8 I !I/ ++!I .?: ; 'I@—B 4: ; I ‰‚1‰‚1Š‚‘B‰‚1.?: ; 'I‡@—B4: ; I?<4: ; I?.?<n: ; % $ >  I: ; ( ( $ > .?: ; ' : ; I .1@—B ++1 ‰‚1 Š‚‘B .?: ; '@—B: ; I1X Y ‰‚1‰‚•B14: ; I‰‚1.?: ; '@—B4: ; I?<.?<n: ; % .?: ; ' .1@—B% U: ; I$ > .?: ; 'I@—B: ; I: ; I4: ; I $ >  ++ I &I% : ; I$ > .?: ; 'I@—B: ; I‰‚1Š‚‘B$ >  4: ; I ++‰‚1  I &I : ; I4: ; I4: ; I?<.?<n% $ > .?: ; 'I@—B: ; I: ; I4: ; I4: ; I 4: ; I ++‰‚1 Š‚‘B ‰‚1 $ >  I&I : ;  I8 4 .?: ; '@—B4: ; II!I/ .?<n: ; % $ > : ; I I: ; ( .: ; 'I : ; I: ; I 4: ; I ++$ >   I .?: ; 'I@—B : ; I4: ; I4: ; I4: ; I4: ; I ++: ;  ++: ; ++: ; 1X Y1 41141‰‚1Š‚‘B1X Y 1RUX Y  U ‰‚1!‰‚1"&I# : ; $ I8 4% &I'!I/ (.?: ;'I@—B): ;I*+4: ;I,.?<n: ; % $ > .?: ; '‡@—B.?: ; '@—B4: ; I4: ; I‰‚•B1 I 4: ; I?< ++I !I/  4: ; I?.?<n: ; % .?: ; '‡@—B% $ >  I: ; ( ( $ > .?: ; 'I@—B‰‚1 Š‚‘B ++.?: ; '@—B : ; I : ; I .?<n: ; % .?: ; '@—B: ; I4: ; I4: ; I$ > $ > .?: ; '@—B% $ > .?: ; '@—B4: ; I‰‚1Š‚‘B‰‚1$ >  ‰‚1 ++‰‚•B1 ‰‚•B1 4: ; I ‰‚•B14: ; I?<.?<n: ; %  I: ; ( $ > .?: ; '@—B: ; I4: ; I.?: ; '@—B 4: ; I ++ I &I 4: ; I?< I!% $ >  I: ; ( ( $ > I!I/ &I ++4: ; I?% $ >  : ;  : ; I 8  I: ; (  : ; I8 .: ; 'I  : ; I ++: ; I 4: ; I $ >  .?: ; '@—B.?: ; 'I@—B: ; I: ; I4: ; I1RUX Y 111RUX Y 1X Y  I.?: ; '@—B: ; I1X Y  411 414: ; I &I!I"!I/ #4: ; I?<$!% $ >  I: ; ( ( $ >  : ;  : ; I8 I ++!I/ &I 4: ; I?%  I: ; ( $ > I!I/ &I4: ; I?% : ; I$ >  I: ; (  : ;  : ; I 8  : ;  : ; I8 ++ : ;  : ; I : ; I  I'I'( $ > .?: ; '@—B: ; I4: ; I‰‚1‰‚1Š‚‘B‰‚•B1‰‚•B14: ; I.?: ;'@—B: ;I4: ;I: ;I .?: ;'@–B!4: ;I".?: ;'@—B#‰‚1$‰‚•B1%4: ; I&&I'4: ; I?<(I)!*.?<n: ; % : ; I$ >  I: ; (  I: ; ( $ >   : ;  ++ : ; I 8  : ;  : ; I8  : ;  : ; I : ; I I.: ; 'I : ; I: ; I.?: ; ' 4: ; I.?: ;' 4: ;I.1@—B41.?: ; '@—B‰‚1‰‚•B14: ; I.?: ; 'I@—B1X Y 1!: ; I"1X Y # $‰‚1%Š‚‘B&‰‚•B1'‰‚1(1RUX Y ) U*‰‚•B1+41,.?: ;'@—B-1RUX Y..?: ;'I@—B/: ;I04: ;I14: ;I24: ;I34: ; I44: ; I?54: ; I?<6.?<n: ; % $ >  I: ; ( ( $ > I!I/ &I ++4: ; I?% : ; I$ >  I: ; (  I: ; ( $ >   : ;  ++ : ; I8 .?: ; ' .?: ; '  4: ; I.1@—B.?: ; '@—B4: ; I‰‚1.1@—B41 41‰‚•B14: ; I.?: ; '@—B‰‚1Š‚‘B‰‚•B14: ; I4: ; I?<.?<n: ; % $ >  I: ; ( ( $ >  : ;  : ; I8 .: ; '  ++: ; I 4: ; I .?: ; '@—B 4: ; I1X Y 1 411RUX Y  U: ; I.?: ; 'I@—B.?: ; '@—B4: ; I4: ; II!I/ &I I4: ; I?<!% $ >  I: ; ( ( $ >  : ;  : ; I8 I ++!I/ &I 4: ; I?% $ >  : ;  : ; I 8  : ;  : ; I8  : ;  : ; I : ; I ++4: ; I?% : ; I$ >  I: ; (  I: ; ( $ >  .: ; 'I  ++: ; I : ; I .: ; '  4: ; I.?: ; 'I .?: ; '@—B.1@—B11 U1 11X Y  4141.: ; 'I@—B: ; I: ; I4: ; I‰‚1Š‚‘B  I!&I".?: ; 'I@—B#.?: ; '@—B$: ; I%‰‚•B1&4: ; I'4: ; I?<(I)!% $ >  I: ; ( ( $ > I!I/ &I ++4: ; I?% $ >  I: ; ( ( $ > I!I/ &I ++4: ; I?%  I: ; ( $ >  : ;  : ; I8 4: ; I?&I I ++!I/ % $ >  I: ; ( ( $ > .: ; ' : ; I .: ; 'I  ++.: ; ' 4: ; I  4: ; I: ; I.?: ; 'I@—B: ; I4: ; I4: ; I4: ; I1RUX Y 11 U4141 1X Y ‰‚1‰‚1Š‚‘B1RUX Y 1X Y U!41" I#&I$.?<n: ; %  I: ; ( $ > I!I/ &I4: ; I?% : ; I$ >  I: ; ( ( $ > .: ; '  : ; I ++4: ; I .: ; 'I  .: ; 'I@—B : ; I: ; I4: ; I1X Y 1 411X Y  I&I.?: ; '@—B.?: ; '@—B: ; I1RUX Y  U.?: ; 'I@—B‰‚1Š‚‘B4: ; I 4: ; I?<!I"!%  I: ; ( $ >  : ;  : ; I8 4: ; I?&I I ++!I/ S2Ÿ 2Ÿ SPóPŸ P (óPŸ8>1Ÿ¾ÎSÎÙœÚ<Sx~5Ÿ<L2Ÿ<L ÿŸLN3ŸLN ÿŸNT4ŸNT ÿŸTV5ŸTV ÿŸhl2Ÿtv2ŸtvS|†P†óPŸ‚†S†P|€1Ÿ†ˆ1Ÿ†ˆPšPš¤óPŸ˜šSš¤P”6Ÿšœ6ŸšœPTPtŸ`TP ++óPŸ P$óPŸ PóPŸ$)P):óPŸ<@0Ÿ@JTJMPMNtŸN”Tx€0ŸQ&óQŸRrŸP$S(,P,4S48sŸ(.0Ÿ.0p s"Ÿ08Q P V &P&<V<BPBNTNTtŸ@BPBFTFTUTVóPŸX^P^jWjntŸnvTv~tŸ~‚W‚†tŸX`Q`jqŸ~€qŸ\^P^†WPóPŸ.P.lóPŸ VU:VTVlPPU^@FVFU ++ÈUÈÔVÔâvŸò8UQ,QüVvŸV˜ÞY¼ÊV<HYP,>P>@~”ÿŸFP ++~”ÿŸ ++ P \|#Ÿ@BPBF|#ŸFHPHP|#ŸPRPRZ|#ŸZ]PbdPd~|#Ÿ~€P€ˆ|#ŸˆŠPŠ’|#Ÿ’”P”œ|#Ÿœ¦P¦®|#Ÿ®¶P¶ÔYØâYâôPôü|#ŸüP |#ŸP|#ŸP,|#Ÿ,4P4J|#ŸJLPLP|#ŸP^P^n|#ŸnpPpx|#ŸxŒPŒ“|#ŸÞàPàè|#ŸèúPú|#ŸP|#Ÿ$P$'|#Ÿ8LYÊÖ|#Ÿð<|#ŸdtPtx|0Ÿx‚V‚„P„Ž|#Ÿž¤P¤Ö|#ŸÖØPØÞ|#Ÿè,|#Ÿ®¶0Ÿ¶Ì\Øò\¦®R8L\jp0Ÿp„\ ++0Ÿ.@ZhnZ ++Z.8ZLÊZÐðZ ++Z$ZŽžZ¶¾ZÞèZZZ,8Z@‘¤Pn@Ÿè:Ÿ.8‘¤LÊ‘¤ÊÌ:ŸÖ ++‘¤$:Ÿdj@ŸŽž‘¤ž¾:ŸÞ葤ø‘¤:Ÿ,8‘¤˜œSœÎ‘ ÎÒSÒ@‘ .8‘ LÊ‘ Öè‘ èðSŽ”‘ ”–S–œ‘ œžSÞè‘ ,8‘ @0Ÿ@‘œ ++0Ÿ ++ä‘œü‘œ$@Y@p‘œpxPxð‘œò²‘œ²ÞVÞ.‘œ8d‘œdjSj†‘œ¢¨S¨‘œ<‘œ<dVdÞ‘œèêPêô‘œôöVö8‘œ@R ++R@]RbîRò R:RJRRn“R“˜‘¤˜¤RÞôR'R8LR$<Rj€R„ŽR¾ÄRÖÞRèøR@ Ÿ ++ Ÿ ++0Ÿ*W,.1Ÿ.8W ++0ŸQT,ZQZ\T\¢^¢ÙQÙÚtŸÚäT ++tŸ ++T<>ty"Ÿ>@T@]Q]bTb Q  ++tŸ ++T>Q>JTJ€Q€ÞTÞ"Q".T68T8jQ¸¼t‘œ"ŸÊÖQÖèTè ++Q ++T<Q<dTdÀQÀÞTèQ,T@S ++SÈY@]Sb S@SJhShnYn“S“˜‘¨˜ªSÞîSîYS'S8LSLPYÊÖYð ++Y ++S$Y$<SdŽSŽ¾Y¾ÎSÖÞSèøSøY$SFP~0.ŸP\r0.Ÿ\˜q0.ŸF˜òÖF˜‘¤F\Z\^R^fSŒS˜RF’‘´Ÿ’”S”˜‘´ŸF\‘´Ÿ\^V^jvŸjV.8VLÊVÖðVŽžVÞèV,8Vj‚S,0Y02V28vŸ8<V¶ºVºÀ[ÀÆ{ŸÆÌ[fjSjnYntyŸtzY¤¨S¨¬Y¬²yŸ²¸YJPYPVyŸV\Y S &s|Ÿ&(SQq€€€Ø{Ÿq€ÀðØ{Ÿ P $p€€€Ø{Ÿ$&p€ÀðØ{Ÿ&(óPŸP(óPŸp Ÿ(óP Ÿ(BPBPóPŸ(Bp ŸBPóP ŸPjPjxóPŸPjp ŸjxóP Ÿ”0Ÿ”žTž¡P¡¢tŸ¢¶TºÊTp˜P˜ qp„Q„ óQŸ ®P®üóPŸ ¦0Ÿ¦® ++p”3&ÿŸ®äu3&ÿŸ¦®p”3&ÿs $Ÿ®äóP#”3&ÿs $Ÿ¦äsäôóP#” ÿ$3&ÿŸæôQü ++P ++DóPŸü0Ÿüp”ÿŸS`hPhxóPŸxŽ0Ÿ‚ŽQ„†R–˜PP\óPŸT,0 tÿp"Ÿ\vPvžUžÖóPŸÖàUà*óPŸ*-P-0U0XóPŸr$T*XTž P ÖUà$U0XU¤©P s2!Ÿ SXpPpžUžÄóPŸÄÔUÔ×P×ÚUÚôóPŸnàTž P ÄUÚàU¤©Pô P :U:ZóPŸZjUjmPmpUpŒóPŸ ++vT:<P<ZUpvU@EPŒ¤P¤ÌUÌðóPŸðúUúýPýUÒ×PÌÎPÎðUP(óPŸpóP#(.P.LULzóPŸ0tTLNPNtURWP€‡P‡VóPŸ<VÎÐ0ŸÐÚTÚÝPÝÞtŸÞT\^P^ŒT¸ºPºàTðòPòT "P"BT`bPbˆT ++q@D$!Ÿ ++Q" qÿÿÿwŸ"0QR^SdjSž¢Sž¢@=$Ÿ²¶S²¶0Ÿ²¶@=$ŸÀÊPÊÔóPŸÄÆSÄÊPÄÊ ++ÿÿŸàâSôøs ÿýŸøSPlóPŸlnPnqDq8óPŸöøS®²s ÿýŸ²´S€ŽPŽ´óPŸ´¸P¸ºóPŸ€¤0Ÿ¤¬P¬´T´¶0Ÿ¶ºT”´U"S ++QQ¼ÂSØÞS0ŸS $V$,R.0V0HRHJvJLVL`R`budlSlnrˆœ0Ÿœ¬Sª®Q®´SÂÄQÄÊSØR2P2PóPŸPdPd€óPŸ€†P†˜óPŸ’pÿŸ˜ž0Ÿž 1Ÿ ¢2Ÿ¢¤3Ÿ¤¦4Ÿ¦¬5ŸsHJ$Ÿ"sHC$Ÿ"&ST^P^|óPŸdhS|ŠPŠšUšœóPŸœžUž P ¢óPŸ|‚Q‚ŠTŠžóQŸž¢T|Š0ŸŠŒPŒ’0Ÿ’šPœžPž¢0Ÿ|Š0Ÿž¢0Ÿ¤¬P¬ÄóPŸ°´p3Ÿ´¸P¸¼pŸÄØ p2$€"ÎÒSÎÖ1ŸÎÖ3Ÿàô p2$€"êîSêò2Ÿêò3Ÿ P LTLZVZÄTÄtŸRrŸ"RNTtŸŠœtŸœÔTÆÞRPTtZ¬WœÔW>¤Ÿ>D,ŸDN°ŸNR´ŸRZ¸ŸZ¬w ++ÿÿŸœÔw ++ÿÿŸ`bPblUflUv¤UœÔUz”S ªS”–syŸ–¢SœžSª¬S€‚r{Ÿ‚ŽQŽ’r{Ÿ ¢Q¢¤r{Ÿ¦¨Q¨ªr{Ÿ¢°°Ÿ¢°0Ÿ°¶´Ÿ¶º¸ŸºÀ¤ŸºÀ €ŸÀÂ0ŸÀ ÿŸÂÄ(ŸÂÄ ÿŸ ¤Ÿ  †Ÿîò0ŸŠ– ÿŸäæ ++ésŸæè ++èsŸèò ++ésŸŠ” ++èsŸîò(ŸŠ–(Ÿîò ÿŸŠ– ÿŸTœŸ$T$@p@D œ°àDJNp (Ÿ  ÿŸ8D ÿŸJN0Ÿ&, ++érŸ,. ++èrŸ.8 ++érŸJN ++érŸ.2$Ÿ8D(ŸJN(Ÿ8D ÿŸJN ÿŸT`¤ŸT`0Ÿ`d°Ÿ`d‘Ldl´Ÿdl‘Hlr¸Ÿlr‘Drx¤Ÿrx‘Tx€,Ÿx€‘PnPnróPŸrtPt|óPŸBQBpuŸpróQŸr|Q0Ÿ2U2BRr|0Ÿs2$w"0Ÿ1Ÿ @<$rŸ " ++ÿÿrŸ",@<$rŸLXt2$w"LX0ŸXZ1ŸZ\@<$sŸ\^ ++ÿÿsŸ^l@<$sŸÐà p2$Œ"Ðà0Ÿàâ1Ÿâä@<$sŸäæ ++ÿÿsŸæî@<$sŸô p2$Œ"ô0Ÿ1Ÿ@<$rŸ ++ ++ÿÿrŸ ++@<$rŸ&P&<óPŸ& p2$Œ"Ü$Žôl` ++Ø l–ü9(<†‚Äx5<V¨” Lè ; (‚0 ˜»È Fz#Ï$ü% ¨ÿ-/ù/HŽBØàðN P¸èS 8]WÝX[Ø -``a“bªdø Ô’k lÌ"Œp8:<>xz|~z|~€œž®°¬®²´<@DFJLBDLNFHRTHJTVô``j<DHJ\ ¢¤¦ªÚÜäªÚÜäÚÜäôüþ¨ª¬´PVhnŒ¦ª°œØÜTVXZ^n8<48<>"&>D*,DFLN .0NR "02RTXZZ¤¬²´ºÞäœÔ¢¤¬°°²´¶¤¨º¼¾À¨¬²´À¼¾ÂÄÊÐÐÔöúÔØþØÚÜÞäòŠŽ’–ØÚîòŠŽ’–ÜÞèêÚÜ&<@DJN&*.88<@DJNTVZ\^`VZ\^bd`bdhjlhjlrÐÒÔØÚôôöøüþQvû src/sys_execsrc/includemsg.cmsg.hprcm_core.hpm_state_data.hstddef.hsync.héÓ./µ.“Jâ.KQ†s q  |\œ#j_!J =">!P.1 -";O ).W *  r  "&//1Yu /JwI äB>.B Ãf½.Ã.“±Ó./µ.ÐJ§Ý.!«.ÚXç./¡ éXuwu^ û src/sys_exec/home/a0274052local/toolchains/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/includesrc/includesys_init.cstdint.hrsc_table.hprcm_core.hcm3.hmsg.htrace.hsync.hdebug.hô ++ 22!-2j0001=>3>ke. `Ç'2¿mû src/sys_execsrc/includesync.cmsg.hcm3.htrace.hprcm_core.hhwmod.hl!/Az / ++ >-@!1>-N$"=#+5k01=CJ<=$.=f@+û src/sys_exectrace.c!X>û src/libsrc/includestring.ctypes.hK-11…u<û src/libsrc/includeputs.ctypes.h< !!"$!","0z. Ö "=-[1 "t/-w„Vû src/libsrc/includedebug.cprintf.hputs.hÄ%%%/ sX?Ÿ!"!>?0!ÙØcû src/libsrc/includeprintf.cputs.hstring.hstddef.h<Ú .s  .t  =0+. tÖaª~Jô  /0= ‚</=0¨~.°gó>ÓJX=LMY",>2!1.=MMM/-03JJ•~t=;ì.¸~.ù ?„.ý ˆ.)&(/!"=K!l´.K>.C.> "==¾.Ç.>=¶× 2K3y &-//0.ä "ó.</"Lò~.Y;0CMA2-v< <-s<<-y-O$"=#+3l-*=@-]!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>4?B2-y=M>=MY/\Y/\hYH PJû src/pm_servicessrc/includehwmod_335x.chwmod.h7û src/pm_servicessrc/includepowerdomain.cio.hmsg.hpowerdomain.hprcm_core.hpowerdomain_335x.hpowerdomain_43xx.h (=!!!!\jY/!!!z./!!! ."//-!!/!!#:fu u  !“ ×t© ×J© ótMn k  (Ÿ[Úgfv/-!"V/"XNHû src/includesrc/pm_servicesdpll.hdpll_335x.cLFû src/includesrc/pm_servicesldo.hldo_335x.c<Áû src/pm_servicessrc/includepm_handlers.cmsg.hclockdomain.hhwmod.hpowerdomain.hdpll.hldo.hprcm_core.hrtc.hcm3.htrace.hstddef.hH!!#?0&z !Ah>LZ11 <y.f&z<&S%1>[KNKA?M010>1<UJX0fLZ$">/AN-H<'<<%7%T$#??[KNK??M0>pJxXz< <#+ ž%7%T$#??[KNK??M0rJxXz<<#+²%7%T$#>[KNK??L>sXvX¬#i-@ %$0>ZK??LY?-O4  K2">K0> ta<$ =",4g=?01=@-`J5ä .9#<P>=>>0000>1-g=>>00>1- ++J#>=>>0?#- <#>=>/0>1-C!1- <#>=>00>0?-â¶û src/pm_servicessrc/includeprcm_core.cio.hhwmod.hdpll.hldo.hmsg.hpowerdomain.hclockdomain.hcm3.hddr.hi2c.hstddef.hØÀ$">=>$">=á}<!/"0-\"#&/!"!L///0-¿'y @ Ä.#M'y µ Ï.#Mª.Ú<\?#!†1 f!#+#M????????f???Mf>=>=>=>=>=>=>=>=>f=HZ-zžtä œ #á<1@+–!00Ì.¸X0>===>-\!====>>1><.H<0 -t$YK=Y%*@u. [ ‚PJû src/pm_servicessrc/includehwmod_43xx.chwmod.hSgû src/pm_servicessrc/includeddr.cprcm_core.hmsg.hhwmod.hstddef.h¸/y.!'z !"!"z ""!"y !!"!"!!!!"L#1<`$!#!&u.!#!&o.//‚#1/!!"!!!"D>4z.&z &v.!)//"/XhY,^8$<y.=/$$"!">/!"m.KL/0f# p ##!?"/-!#=N?,0”!M>L1-”!M>L1-•L//kL//pû src/pm_servicessrc/includedpll.cdpll.hprcm_core.hdpll_335x.hdpll_43xx.h ö#¬tu/#/!!#/-!/#/!!#/!/#/!/[6x‡M¢kY/!)/!/  !![(x !"?0/ NHû src/includesrc/pm_servicesdpll.hdpll_43xx.cQKû src/includesrc/pm_servicesmsg.hpm_state_data.c û src/pm_servicessrc/includeclockdomain.cio.hprcm_core.hclockdomain_335x.hclockdomain_43xx.hstddef.hclockdomain.hØjY/!zJ/! J!%j.h<#t M #X!;M)D[#u?P.h<J2XT._<#J.Xjj\Vû src/pm_servicessrc/includeclockdomain_43xx.cclockdomain.h\Vû src/pm_servicessrc/includeclockdomain_335x.cclockdomain.h\Vû src/includesrc/pm_servicespowerdomain.hpowerdomain_43xx.c2Bû src/pm_servicessrc/includei2c.cdpll.hø ž.â. s ˜ è ˜.ð.Ý £ ð. )3õX‹<õJ‹.: > <>H"/=>h!>¨J†ú~<•Ó ¼<q. k.Œ.ô~..ô~ ˜.è~<™X-è~ ˜ ’f)`.#.X<œ.ä~.«.Õ~<†.ú~<¨X1Õ~<‰.÷~.«.«<)LFû src/includesrc/pm_servicesldo.hldo_43xx.cÿ€û src/pm_servicessrc/includehwmod.cprcm_core.hhwmod_335x.hhwmod_43xx.hstddef.hhwmod.hÌ"È93;o h/J¾//` h/J3G‚jY/!zJ/!8JZ' Y '.Y L/)f_" ^ ".^ L/$‚b.€  ˆ p  t Ä$ºÄ$%ì$0Éñÿ è ÔÞñÿ  däñÿ 0 |  € ¤  ¨ ´  ¸ Ä ¬êñÿ È à  ä ˜  œ  þñÿ   $4 8L Pd hx ñÿø$ñÿ  ´ ¸ð < @˜ œà äü  D ( 28;<D@ØLñÿ`%Xñÿˆ&cñÿ H  ¤„  , <Ä ÔH Xx „ð ø˜qñÿ Ø}Ùì ðšñ   $\ p€ „” ˜¨ ¬À ÈÔ Ø   ¬ð ôP X¤ ¨´D¸D„ ++Éñÿ&Öñÿ ¸ø \ ˆÜ   $ˆ °Ü àô ( 4\ h| „˜HÜH ãñÿ  $ (¸ ¼ì ð 4 8H L„  Ðü&dêdúhl,  ñÿ 'ñÿX)ñÿ Ø  , P  T 7U &˜  œ ´  ¸ Ð  Ô Ü  à è  ì ô €K€R„_ˆü nñÿ4(ñÿ¤(”ñÿ)§ñÿ ø ¨"¨­ñÿ)¸ñÿ Ì"ÀÍ"|D# H#|# œ#¼# À#ä# è#$ $$ $,$ 0$@$ D$T$ŒÔŒÛì”ôñÿ˜)=<&6ÉAÅWá c0y• "‰”¨)8¤¥ü¶™ HÄ)Ó ÜõdçHýu ')%” .>TK˜)Z`%u$¡œŸ!¬• "½´Åí Ù± êlX  • "0.ñ07Y DHeYù Ôcq)”‹Ù œ©³É‰xß• "ï‘• "%Ø(@3• "Cõ TqnI#Tyă1 “)¤œ·Õ„Ê• "Úyß• "ï½4ú 'ˆ Å .• "?1H• "YynU,}ˆp •ñ §• "¸Ì Ù‰pí• "ý $‘.˜;å ^LY (]¡8qe,‚4‹• "œÙT­É ¾Êý ÖY:êÉFûm ++ • " ½+ á 7 • "H iV 4*` …p Q Ù8˜ 1$´ • "Å • Ó ¹Xä   ð µ ++p% ++¸ ++( ++=80 ++%Œ> ++• "N ++()8^ ++¸ l ++• "} ++ ++• "ž ++¹ µ ++QÄ ++$%<Ò ++ (á ++¹ ì ++• "ý ++• " ¤($ Y7 © L • "] 9h í y ©– • "§ µ É¼Ê •.Ð 54Ø • "é ø$  9 à)0/ • "@  Q ñÿ\ ¹dp  ~ ù6’ y£ ¨&» a0Ó =ä ë ¼ò #$ÿ a ++ %L   . ? QO ©Xe d o • "€ é# ‘ ™œ E$· œ Ç - (Ú ù í • "ý ±0}  !¬ *¡; G• "X• "i­Hqˆ&1 (‘¡£$²åèÎõlÙ4(ïd(@ý¬ ++…2 HqR^•r%ƒÀŒí ži8§² ÃÙØ%ð• "A é I\)Õ 6¡ˆFE W• "h™~=˜| ™•®¬(,™ÜÄDä¡6ÿ`)0Ål)#1.7A\M% Z• "k• "|Ä’£­­…Æ• "Ö<((êÀ&<øÁ#(‘ÄMT#°,• "startup.c$tzero_loop$dmsg.ca8_version_handlera8_reset_handlercustom_state_datasys_init.csync.ctrace.cstring.cputs.clogbuf_posdebug.clevelsdebug_leveldebug_idxprintf.chex2ascii_dataexception_handlers.crtc.ccm3.cext_intr_handlers.cldo.cldo_regshwmod_335x.cpowerdomain.cpd_statesmpu_bitsper_bitspd_regsdpll_335x.cldo_335x.cpm_handlers.cprcm_core.cprcm_enable_isolation.part.0prcm_disable_isolation.part.1cmd_wake_sourceshwmod_43xx.cddr.cio_ctxdpll.cpower_down_pllsdpll_regspll_modedpll_43xx.cpm_state_data.cclockdomain.cclkdms_state_changeclkdmssleep_clkdmsstandby_clkdmsclockdomain_43xx.cclockdomain_335x.cpowerdomain_43xx.ci2c.cldo_43xx.chwmod.chwmods_state_changehwmodsessential_hwmodsinterconnect_hwmodspowerdomain_335x.cputcharam43xx_interconnect_hwmodsdisable_ioa8_standalone_handlervtp_disableverify_pd_transitionsextint8_handlertimer_syncam335x_per_bitsa8_lp_ds0_handlerreset_handleram43xx_pd_regspm_resetds_restoreget_pd_mpu_stctrl_valprintfam43xx_dpll_regsam43xx_ldo_regsds1_data_aux_data_startcmd_handlersam335x_pd_regsam335x_pg2_power_down_pllsessential_hwmods_enablea8_lp_ds1_handlerdpll_get_divextint27_handlersoc_revclkdms_standby_wakeextint36_handlerddr_am335x_io_suspendidle_v2_dataextint26_handlerpd_state_changepll_lockextint34_handlerextint48_handleri2c_writepd_read_stateplls_power_up_start_dataextint41_handlerprcm_disable_isolationtrace_set_current_posddr_am437x_io_suspendextint4_handlera8_m3_low_power_fastextint50_handlerextint0_handleram335x_clkdmsextint7_handlerbusfault_handlerdisable_master_oscillatorhwmod_init_end_datadebug_set_levelextint45_handlerclear_wake_sourcesa8_standby_handlerextint9_handlerputssystick_handlerpll_bypassam43xx_power_down_pllsds1_data_hsextint40_handlerextint37_handlermsg_readextint12_handlera8_m3_low_power_syncm3_param_resettrace_initstandby_datamemmanage_handlerextint30_handlerm3_firmware_versiontrace_updatea8_wake_ds0_handlerextint5_handleressential_hwmods_disablea8_wake_cpuidle_handlerio_isolationextint31_handlernvic_disable_irqget_master_xtal_khzmsg_cmd_is_validvtt_highextint19_handlerclockdomain_initextint16_handler_start_textsvc_handlera8_i2c_wake_handlerextint53_handlera8_notifyextint1_handlermsg_cmd_needs_triggerclkdms_wakeextint15_handlerset_ddr_reset_end_textclear_ddr_resetextint47_handlerconfigure_wake_sourcesinterconnect_hwmods_disableextint18_handlerdummy_handlerpowerdomain_initds0_data_hsextint52_handleram335x_dpll_regssoc_typevector_tablevprintfddr_io_resumeextint6_handleram43xx_per_bitsrtc_mode_dataextint23_handlerldo_wait_for_onextint20_handlerscr_enable_sleeponexitldo_power_downam335x_hwmodsnvic_clear_irqclkdm_wakeextint38_handlerextint22_handleram335x_standby_clkdmsa8_cpuidle_handlerscr_enable_sleepdeepextint39_handlerdpll_resetextint42_handlermsg_cmd_wakeup_reason_updateextint21_handler_logbuf_startgeneric_wake_handlerputsnvtt_lowextint32_handleram335x_interconnect_hwmods_aux_data_endldo_power_upam335x_mpu_bitsextint28_handlerdebugmon_handler_end_stackddr_io_save_contextrtc_reg_writea8_wake_ds1_handlerextint49_handleram43xx_essential_hwmodsa8_wake_standby_handlerextint46_handlermemsetsoc_idhwmod_enablemainsetup_socpendsv_handlerextint43_handlerrtc_enable_checkmsg_cmd_read_idinit_m3_state_machineidle_dataextint25_handlerhwmod_is_enabledvtt_toggleinterconnect_hwmods_enablecmd_global_dataclkdm_state_changeusagefault_handlerextint3_handlervtp_enableclkdm_active_logbuf_endds0_dataextint51_handlerclkdm_sleepextint24_handlerextint10_handlerds_saveam335x_ldo_regsnvic_enable_irqpowerdomain_resetddr_io_suspendpd_state_restoredebug_haltam335_initam43xx_standby_clkdmsam43xx_clkdmsvtt_gpio_pin_end_resource_tablea8_wake_rtc_handlertrace_get_current_posa8_cpuidle_v2_handlermsg_cmd_stat_updateldo_wait_for_ret_end_bsshardfault_handlerldo_init_start_bssextint35_handlermsg_cmd_fast_triggeram335x_essential_hwmodsextint14_handlermsg_writenmi_handlera8_lp_rtc_handlerclkdms_sleepplls_power_downextint33_handlerextint13_handlerprcm_enable_isolationa8_lp_ds2_handlerds2_dataa8_i2c_sleep_handleram335x_sleep_clkdmsconfigure_deepsleep_countrsc_taba8_wake_cpuidle_v2_handleram43xx_mpu_bitsdebug_printfstrlena8_wake_ds2_handlerget_pd_per_stctrl_valrtc_reg_readextint29_handlerextint11_handler_start_resource_tableextint44_handlerenable_ioenable_master_oscillatorextint2_handleram43xx_sleep_clkdmsam43xx_hwmodshwmod_disablemsg_cmd_dispatcherdpll_initmem_typeextint17_handler4*!Ä'ÄÄD7¸<FN3rZ;t'$hb˜Â,s$ÅЂôÈ€tÎ#œ0—èé§0€-°p­7À东Ílp$U Ü:= +\ No newline at end of file +diff -Naur --no-dereference a/firmware/am43x-evm-scale-data.bin b/firmware/am43x-evm-scale-data.bin +--- a/firmware/am43x-evm-scale-data.bin 1969-12-31 19:00:00.000000000 -0500 ++++ b/firmware/am43x-evm-scale-data.bin 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1 @@ ++ Wd$k$Š$g$†d$k$™$g$† +\ No newline at end of file +diff -Naur --no-dereference a/firmware/regulatory.db b/firmware/regulatory.db +--- a/firmware/regulatory.db 1969-12-31 19:00:00.000000000 -0500 ++++ b/firmware/regulatory.db 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,21 @@ ++RGDB00¹ADôAEqAF~AI‹ALáAM`AN~ARqASAATåAUÆAW~AZuBAôBB—BD®BEåBFqBGåBHcBL~BMABNˆBO©BR$BSžBT~BY~BZÃCA1CFfCHïCIqCLˆCNýCOqCR\CUCXžCYåCZåDEåDKåDM:DO:DZ”ECEEåEGÅESåET~FIåFMAFRêGBøGD=GExGF‹GHqGL‹GP‹GRåGT:GU6GY¼HK)HNqHRÜHTAHUåIDIEåILPIN´IR®ISôITåJMqJO‘JPKKEŽKH~KN„KPEKR KW{KYžKZÑLBqLC„LIôLK\LS~LTåLUåLVåMA{MCáMDáMEáMF‹MHAMKôMNžMO°MPAMQ‹MR~MTåMUžMVÙMW~MXqMYšNG¦NIANLåNOïNPˆNZ¸OM~PA-PEqPF‹PGqPHÍPKTPLåPM‹PR=PTåPWAPYžQA RE‹ROåRSôRURWqSA~SEåSGSIåSKåSNqSR~SVYSYITC¢TD~TGjTHqTN{TRÕTTqTW TZ¬UAUGžUS¿UY—UZ{VC~VEÀVIAVNmVUqWF‹WSjYEIYT‹ZAZW~#4JJ#4FJÐ …8)Ð ¸ Ãp Ë@Ð ¸ Ë@ À>€ ¸ ö8 À  ¸ À)@ ¸$Ÿ%¸@œ@Ð$Ÿ%å,œ@Ð$Ÿ%å,œ@ü$Ÿ%å,œ@ý$Ÿ%å,œ@ ++Š$Ÿ%å,œ@ ¸$Ÿ%å,œ@$Ÿ%å,œ@$Ÿ%å,œ@Ð$¦Ð%¸@œ@ ¸$¦Ð%¸@œ@Ð$¦Ð%ßPN Ð$¦Ð%ßPœ@ü$¦Ð%ßPœ@ ¸$¦Ð%ßPœ@Ð$¦Ð%å,œ@Ð%}¨%ßPN Ð%À&0N  Ð%À&0N üJë°L$0œ@üN•0OÍ°œ@¢N•0PÐ8€ÐN•0PÐ8€±üN•0PÐ8€üN•0PÐ8€±üN•0PÐ8€üN•0PÐ8€±ýN•0PÐ8€ýN•0PÐ8€±ýN•0PÐ8€ýN•0PÐ8€± ++ŒN•0PÐ8€ ¸N•0PÐ8€N•0PÐ8€ýN•0Pið8€ÐN•0Q¢p8€ýN•0Q¢p8€ ++ýN•0Q¢p8€ÐN•0Q¢pq¤NãPPÐN NãPPÐN ÐNãPPÐN ¤NãPPÐœ@ÐNãPPÐœ@¤NãPPÐ8€¤NãPPÐ8€NãPPÐ8€ÐNãPPÐ8€ÐNãPPÐ8€±ÐNãPPÐ8€üNãPPÐ8€üNãPPÐ8€ `NãPPÐ8€ `NãPPÐ8€±¤OÍ°PÐN PÐQTPN ÐPÐQTPN üPÐQTPN  `PÐQTPN ÐPÐQTPœ@ `PÐQTPœ@PÐQTP8€ÐPÐQTP8€ÐPÐQTP8€±ÐPÐQTP8€±ÐPÐQTP8€üPÐQTP8€ `PÐQTP8€ `PÐQTP8€ `PÐQTP8€± ¸PÐQTP8€ÐPÐQ¢p8€ÐPÐQ¢p8€±ÐPÐQ¢p8€ÐPÐQ¢p8€±0PÐQ¢p8€üPÐQ¢p8€üPÐQ¢p8€ýPÐQ¢p8€±ýPÐQ¢p8€ `PÐQ¢p8€ `PÐQ¢p8€ ++ŒPÐQ¢p8€ ¸PÐQ¢p8€ÐPiðQ¢p8€ `Sw0Us8€ ++ŠSw0Us8€ÐSw0Uš8€ ]Sw0W[H8€ÐSw0W[HqÐSw0W[HqÐSw0W[Hq±0Sw0W[Hq `Sw0W[Hq ++ŠSw0W[Hq± ++ŠSw0W[Hq± ++ŒSw0W[Hq± ++ŒSw0W[Hq ¸Sw0W[HqüSw0WnÐq `Sw0WnÐq ++ŠSw0WnÐq± ++ŒSw0WnÐq ¸SÅPTýÐ8€ ¸SÅPUè0N  `SÅPV6PqüSÅPV„pq ++ŒSÅPW °œ@ ++ŒSÅPW °q ++ŒSÅPW °q± ¸SÅPW °q ¸SÅPW °q `SÅPWnÐN  `SÅPWnÐœ@ `SÅPWnÐ8€ ÐSÅPWnÐqüSÅPWnÐq `SÅPWnÐq `SÅPWnÐq± ¸SÅPWnÐqüSØØb ¨q±ýUšW[H8€ `V6PWnÐ8€ ++ŠV6PWnÐ8€ÐV6PYCqýW[HXáè8€ÐW[HYC8€ÐW[HYC8€üW[HYC8€ýW[HYC8€ýW[HYC8€ `W[HYC8€ ¸W[HYC8€ ¸W[HYC8€ äW[HYC8€W[HYC8€uW[HY¥88€ÐW[HY¥88€ýW[HY¥88€ ¸W[HY¥88€ ¸WnÐYC8€WnÐYC8€WnÐYC8€üW‚XX˜œ@ ¸W‚XXºØN  ¸W‚XXºØ8€ÐW‚XYøN  ¸W‚XYøN  ¸W‚XYøœ@ÐW‚XYø8€ÐW‚XYø8€üW‚XYø8€ `W‚XYø8€ ¸W‚XYø8€uYCY¥8N  ++ŒYCYóXœ@xZhˆb ¨qÐZhˆb ¨q ]Zhˆb ¨q ]Zhˆb ¨q±ýZhˆb ¨âÜZhˆl¸q°Zhˆl¸â ++°Zhˆl¸âüZ¶¨b ¨q±ýZ¶¨b ¨q± ]Z¶¨b ¨âÌeÀ@Ð õ€èeÀ@ï€ õ€BeÀ@ï€ õ€ `eÀ@ï€ õ€ eÀ@ï€ õ€ eÀ@ï€ õ€ÌeÀ@ï€ õ€ eÀ@;_À õ€ÍeÀ@;_À õ€ ++ðiiÀŠ_@ õ€iiÀÌJ@ õ€ iiÀ;_À õ€0Š_@ÌJ@ õ€ ++ðÌJ@í?À õ€ ¹ñ —Ú¬:© ½ÁÉÍ*nNo­ ÅÉíEü2ÎJZ¡Ñ* OîÑ3üBÞ‘Ñ7Õ]Á‘Ñ<óÚÑ@Ss‘ÑISÑISs‘ÑISsÑISxÑIS‘ÑIrê^Ñ^ú¥±µÑjÒV•Õ%FÞ‰ÕEB•Ù¬ó>âg™Ý<óò}‘Ýf:æábÖå!Kòå* jò‘åN"böoé3 wRéV&fþõ3.ÊFkõn¼ .õ†ÞFõ†æ´Fõ£æ´Fùv´"ýýŽÌ°c…ýEX ++ýZ*6Æ‘ýn¸.ýn¼ .ýr°ýv´*ýzĤ2ý~À‹ý‚â¨Fý†æ´FýŠÈýŠÈ‘ýŽÌýŽÌýŽÌ˜ýŽÌœ&ýŽÌ6ý’Гý›{ý›>ýŸÞ‡ýŸÞFý£æƒBý£æ´Fý§ê¸FýïFýïFýFýFŸÞ½FRO†æ´FŸÞ°FŸÞFF .÷‘ +\ No newline at end of file +diff -Naur --no-dereference a/firmware/regulatory.db.p7s b/firmware/regulatory.db.p7s +--- a/firmware/regulatory.db.p7s 1969-12-31 19:00:00.000000000 -0500 ++++ b/firmware/regulatory.db.p7s 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,3 @@ ++0‚9 *†H†÷  ‚*0‚&10  `†He0  *†H†÷  ‚«0‚§0‚aÀ8e«ÜùKЬðlrHÛÆ0  *†H†÷  01 0 U wens0  231201074114Z21231107074114Z01 0 U wens0‚"0  *†H†÷ ‚0‚ ++‚©z,xM§-2R .lïˆŶiTCyS·®ˆþÀ·]GŽáﳆÚÓdÎ]žKnX>²o^BGAô,¸¨ÔªÀæHð¨ÎË®7¯ö@9ËUo[O…4æiPr^NLº86 Îs8×'*yá¬Ï°'…†“«ìBw7eŠDËÖB“’ã9EÅnJËB+%Œ¸;6YÞBÎ!æ¶Çn^&÷ŠWž¥–r·2ë+sâOfXšë¶«P‹Ãú ++™Â%¿-kªæ>_ëm›]MBƒ-9¸É¬Û:‘Pß»±vmsýÆækqžg6"ƒy±Ö¸„R¯–[ÃcNxpW0  *†H†÷  ‚$(î"t|úl³ÑÂ=})Bˆ­‚¥±ŠÐì\‘ ö‚ýÕg`_1õ½ˆ‘p½¸¹ŒˆþSÉT›CÄzCtkÝ°±;3EFx£ïTh÷…œäQo¯Û*{{o¨œgØËÉ‘@®Ù¡ŸÝ¦C({ªé„ÛvdBpÉÀ뮄hN„ž~’6î;cëy„¯ÈšÇ4Ó”KÑ(—¾ÑEuÜ5b¬··‡È˜À$1VíÛÆF¿Km¦Õ«Ì`üå7¶S}X•©VÇ÷îàv÷eMSúÿ_v3Zú†’ZúüòŒBm·~·´ðǃ»¢-Ô*c?÷1.@3\F¼›Á¥ENÃ1‚R0‚N0'01 0 U wensaÀ8e«ÜùKЬðlrHÛÆ0  `†He0  *†H†÷ ‚[€oˆ/'úÄÊAËs(Þ`œËálB•Ü 9S&‹î?"žwS ("†:zˆD)3™dÿeÄ»ƒY:À}ó‚À%ÛL/±’:ÿ¹ˆK>m…Cj!¯ÄXtIücÌ£TC‰ÜÖ18ªŸ4ÑîŽ[Ç(.efýZ;ÄýS u‹.fÌ–нÉkWáp"™Mé.ù—àËØ­«çb>èL/}Òã·w™øÎ" ²¢ç@­›˜˜W¯B^x:am‰”¬vÁÑñ²]‘kY’½e»4[5$µ Ø¿Ÿ$§1e|®$‚;õ•õEÞ¸;ö²¿ü–†:û£¤ s‹!\.Ù +\ No newline at end of file +diff -Naur --no-dereference a/.github/FUNDING.yml b/.github/FUNDING.yml +--- a/.github/FUNDING.yml 1969-12-31 19:00:00.000000000 -0500 ++++ b/.github/FUNDING.yml 2024-03-28 11:26:09.889017411 -0400 +@@ -0,0 +1,12 @@ ++# These are supported funding model platforms ++ ++github: beagleboard # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] ++patreon: beagleboard # Replace with a single Patreon username ++open_collective: # Replace with a single Open Collective username ++ko_fi: # Replace with a single Ko-fi username ++tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel ++community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry ++liberapay: # Replace with a single Liberapay username ++issuehunt: # Replace with a single IssueHunt username ++otechie: # Replace with a single Otechie username ++custom: https://paypal.me/beagleboard # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +diff -Naur --no-dereference a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md +--- a/.github/ISSUE_TEMPLATE/bug_report.md 1969-12-31 19:00:00.000000000 -0500 ++++ b/.github/ISSUE_TEMPLATE/bug_report.md 2024-03-28 11:26:09.889017411 -0400 +@@ -0,0 +1,20 @@ ++--- ++name: Bug report ++about: Create a report to help us improve ++title: '' ++labels: '' ++assignees: '' ++ ++--- ++ ++**Describe the bug** ++A clear and concise description of what the bug is. ++ ++**Describe how to reproduce the bug** ++List all the steps needed to reproduce the bug ++ ++**REQUIRED INFORMATION** ++Run this command and paste the output here: ++``` ++sudo /opt/scripts/tools/version.sh ++``` +diff -Naur --no-dereference a/.gitlab-ci.yml b/.gitlab-ci.yml +--- a/.gitlab-ci.yml 1969-12-31 19:00:00.000000000 -0500 ++++ b/.gitlab-ci.yml 2024-03-28 11:26:09.889017411 -0400 +@@ -0,0 +1,29 @@ ++image: robertcnelson/beagle-devscripts-kernel-debian-12-amd64 ++# https://git.beagleboard.org/beagleboard/ci-docker-images ++ ++cache: ++ key: "$CI_PROJECT_NAME-ti-linux-arm32-6.6.y" ++ paths: ++ - ccache.tar.lz4 ++ ++build: ++ tags: ++ - docker-amd64 ++ stage: build ++ script: ++ - mkdir -p /root/.cache/ccache/ || true ++ - tar --use-compress-program=lz4 -xf ccache.tar.lz4 -C / || true ++ - ccache -s ++ - CORES=$(getconf _NPROCESSORS_ONLN) ++ - make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf- clean ++ - make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf- bb.org_defconfig ++ - echo "make -j${CORES} ARCH=arm KBUILD_DEBARCH=armhf CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf- LOCALVERSION=-ti-arm32-r$CI_JOB_ID KDEB_SOURCENAME=linux-upstream KDEB_COMPRESS=xz bindeb-pkg" ++ - make -j${CORES} ARCH=arm KBUILD_DEBARCH=armhf KDEB_PKGVERSION=1xross CROSS_COMPILE="ccache /usr/bin/arm-linux-gnueabihf-" LOCALVERSION=-ti-arm32-r$CI_JOB_ID KDEB_SOURCENAME=linux-upstream KDEB_COMPRESS=xz bindeb-pkg ++ - mv ../*.deb ./ ++ - ccache -s ++ - tar --use-compress-program=lz4 -cf ccache.tar.lz4 /root/.cache/ccache/ ++ artifacts: ++ expire_in: 28 days ++ name: "$CI_PROJECT_NAME-$CI_JOB_ID" ++ paths: ++ - "linux-image-*.deb" +diff -Naur --no-dereference a/include/dt-bindings/board/am335x-bone-pins.h b/include/dt-bindings/board/am335x-bone-pins.h +--- a/include/dt-bindings/board/am335x-bone-pins.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/include/dt-bindings/board/am335x-bone-pins.h 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,253 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2020 Deepak Khatri ++ * See Cape Interface Spec page for more info on Bone Buses ++ * https://elinux.org/Beagleboard:BeagleBone_cape_interface_spec ++ */ ++ ++#ifndef _DT_BINDINGS_BOARD_AM335X_BONE_PINS_H ++#define _DT_BINDINGS_BOARD_AM335X_BONE_PINS_H ++ ++#define bb_device 0 ++#define board_soc AM335X ++ ++#define gpio_P8_03 &gpio1 6 ++#define gpio_P8_04 &gpio1 7 ++#define gpio_P8_05 &gpio1 2 ++#define gpio_P8_06 &gpio1 3 ++#define gpio_P8_07 &gpio2 2 ++#define gpio_P8_08 &gpio2 3 ++#define gpio_P8_09 &gpio2 5 ++#define gpio_P8_10 &gpio2 4 ++#define gpio_P8_11 &gpio1 13 ++#define gpio_P8_12 &gpio1 12 ++#define gpio_P8_13 &gpio0 23 ++#define gpio_P8_14 &gpio0 26 ++#define gpio_P8_15 &gpio1 15 ++#define gpio_P8_16 &gpio1 14 ++#define gpio_P8_17 &gpio0 27 ++#define gpio_P8_18 &gpio2 1 ++#define gpio_P8_19 &gpio0 22 ++#define gpio_P8_20 &gpio1 31 ++#define gpio_P8_21 &gpio1 30 ++#define gpio_P8_22 &gpio1 5 ++#define gpio_P8_23 &gpio1 4 ++#define gpio_P8_24 &gpio1 1 ++#define gpio_P8_25 &gpio1 0 ++#define gpio_P8_26 &gpio1 29 ++#define gpio_P8_27 &gpio2 22 ++#define gpio_P8_28 &gpio2 24 ++#define gpio_P8_29 &gpio2 23 ++#define gpio_P8_30 &gpio2 25 ++#define gpio_P8_31 &gpio0 10 ++#define gpio_P8_32 &gpio0 11 ++#define gpio_P8_33 &gpio0 9 ++#define gpio_P8_34 &gpio2 17 ++#define gpio_P8_35 &gpio0 8 ++#define gpio_P8_36 &gpio2 16 ++#define gpio_P8_37 &gpio2 14 ++#define gpio_P8_38 &gpio2 15 ++#define gpio_P8_39 &gpio2 12 ++#define gpio_P8_40 &gpio2 13 ++#define gpio_P8_41 &gpio2 10 ++#define gpio_P8_42 &gpio2 11 ++#define gpio_P8_43 &gpio2 8 ++#define gpio_P8_44 &gpio2 9 ++#define gpio_P8_45 &gpio2 6 ++#define gpio_P8_46 &gpio2 7 ++#define gpio_P9_11 &gpio0 30 ++#define gpio_P9_12 &gpio1 28 ++#define gpio_P9_13 &gpio0 31 ++#define gpio_P9_14 &gpio1 18 ++#define gpio_P9_15 &gpio1 16 ++#define gpio_P9_16 &gpio1 19 ++#define gpio_P9_17 &gpio0 5 ++#define gpio_P9_18 &gpio0 4 ++#define gpio_P9_19 &gpio0 13 ++#define gpio_P9_20 &gpio0 12 ++#define gpio_P9_21 &gpio0 3 ++#define gpio_P9_22 &gpio0 2 ++#define gpio_P9_23 &gpio1 17 ++#define gpio_P9_24 &gpio0 15 ++#define gpio_P9_25 &gpio3 21 ++#define gpio_P9_26 &gpio0 14 ++#define gpio_P9_27 &gpio3 19 ++#define gpio_P9_28 &gpio3 17 ++#define gpio_P9_29 &gpio3 15 ++#define gpio_P9_30 &gpio3 16 ++#define gpio_P9_31 &gpio3 14 ++#define gpio_P9_41 &gpio0 20 ++#define gpio_P9_41A &gpio0 20 ++#define gpio_P9_41B &gpio3 20 ++#define gpio_P9_91 &gpio3 20 ++#define gpio_P9_42 &gpio0 7 ++#define gpio_P9_42A &gpio0 7 ++#define gpio_P9_42B &gpio3 18 ++#define gpio_P9_92 &gpio3 18 ++#define gpio_A15 &gpio0 19 ++ ++#define P8_03(mode) AM33XX_IOPAD(0x0818, mode) /* R9: gpmc_ad6 */ ++#define P8_04(mode) AM33XX_IOPAD(0x081c, mode) /* T9: gpmc_ad7 */ ++#define P8_05(mode) AM33XX_IOPAD(0x0808, mode) /* R8: gpmc_ad2 */ ++#define P8_06(mode) AM33XX_IOPAD(0x080c, mode) /* T8: gpmc_ad3 */ ++#define P8_07(mode) AM33XX_IOPAD(0x0890, mode) /* R7: gpmc_advn_ale */ ++#define P8_08(mode) AM33XX_IOPAD(0x0894, mode) /* T7: gpmc_oen_ren */ ++#define P8_09(mode) AM33XX_IOPAD(0x089c, mode) /* T6: gpmc_be0n_cle */ ++#define P8_10(mode) AM33XX_IOPAD(0x0898, mode) /* U6: gpmc_wen */ ++#define P8_11(mode) AM33XX_IOPAD(0x0834, mode) /* R12: gpmc_ad13 */ ++#define P8_12(mode) AM33XX_IOPAD(0x0830, mode) /* T12: gpmc_ad12 */ ++#define P8_13(mode) AM33XX_IOPAD(0x0824, mode) /* T10: gpmc_ad9 */ ++#define P8_14(mode) AM33XX_IOPAD(0x0828, mode) /* T11: gpmc_ad10 */ ++#define P8_15(mode) AM33XX_IOPAD(0x083c, mode) /* U13: gpmc_ad15 */ ++#define P8_16(mode) AM33XX_IOPAD(0x0838, mode) /* V13: gpmc_ad14 */ ++#define P8_17(mode) AM33XX_IOPAD(0x082c, mode) /* U12: gpmc_ad11 */ ++#define P8_18(mode) AM33XX_IOPAD(0x088c, mode) /* V12: gpmc_clk */ ++#define P8_19(mode) AM33XX_IOPAD(0x0820, mode) /* U10: gpmc_ad8 */ ++#define P8_20(mode) AM33XX_IOPAD(0x0884, mode) /* V9: gpmc_csn2 */ ++#define P8_21(mode) AM33XX_IOPAD(0x0880, mode) /* U9: gpmc_csn1 */ ++#define P8_22(mode) AM33XX_IOPAD(0x0814, mode) /* V8: gpmc_ad5 */ ++#define P8_23(mode) AM33XX_IOPAD(0x0810, mode) /* U8: gpmc_ad4 */ ++#define P8_24(mode) AM33XX_IOPAD(0x0804, mode) /* V7: gpmc_ad1 */ ++#define P8_25(mode) AM33XX_IOPAD(0x0800, mode) /* U7: gpmc_ad0 */ ++#define P8_26(mode) AM33XX_IOPAD(0x087c, mode) /* V6: gpmc_csn0 */ ++#define P8_27(mode) AM33XX_IOPAD(0x08e0, mode) /* U5: lcd_vsync */ ++#define P8_28(mode) AM33XX_IOPAD(0x08e8, mode) /* V5: lcd_pclk */ ++#define P8_29(mode) AM33XX_IOPAD(0x08e4, mode) /* R5: lcd_hsync */ ++#define P8_30(mode) AM33XX_IOPAD(0x08ec, mode) /* R6: lcd_ac_bias_en */ ++#define P8_31(mode) AM33XX_IOPAD(0x08d8, mode) /* V4: lcd_data14 */ ++#define P8_32(mode) AM33XX_IOPAD(0x08dc, mode) /* T5: lcd_data15 */ ++#define P8_33(mode) AM33XX_IOPAD(0x08d4, mode) /* V3: lcd_data13 */ ++#define P8_34(mode) AM33XX_IOPAD(0x08cc, mode) /* U4: lcd_data11 */ ++#define P8_35(mode) AM33XX_IOPAD(0x08d0, mode) /* V2: lcd_data12 */ ++#define P8_36(mode) AM33XX_IOPAD(0x08c8, mode) /* U3: lcd_data10 */ ++#define P8_37(mode) AM33XX_IOPAD(0x08c0, mode) /* U1: lcd_data8 */ ++#define P8_38(mode) AM33XX_IOPAD(0x08c4, mode) /* U2: lcd_data9 */ ++#define P8_39(mode) AM33XX_IOPAD(0x08b8, mode) /* T3: lcd_data6 */ ++#define P8_40(mode) AM33XX_IOPAD(0x08bc, mode) /* T4: lcd_data7 */ ++#define P8_41(mode) AM33XX_IOPAD(0x08b0, mode) /* T1: lcd_data4 */ ++#define P8_42(mode) AM33XX_IOPAD(0x08b4, mode) /* T2: lcd_data5 */ ++#define P8_43(mode) AM33XX_IOPAD(0x08a8, mode) /* R3: lcd_data2 */ ++#define P8_44(mode) AM33XX_IOPAD(0x08ac, mode) /* R4: lcd_data3 */ ++#define P8_45(mode) AM33XX_IOPAD(0x08a0, mode) /* R1: lcd_data0 */ ++#define P8_46(mode) AM33XX_IOPAD(0x08a4, mode) /* R2: lcd_data1 */ ++#define P9_11(mode) AM33XX_IOPAD(0x0870, mode) /* T17: gpmc_wait0 */ ++#define P9_12(mode) AM33XX_IOPAD(0x0878, mode) /* U18: gpmc_be1n */ ++#define P9_13(mode) AM33XX_IOPAD(0x0874, mode) /* U17: gpmc_wpn */ ++#define P9_14(mode) AM33XX_IOPAD(0x0848, mode) /* U14: gpmc_a2 */ ++#define P9_15(mode) AM33XX_IOPAD(0x0840, mode) /* R13: gpmc_a0 */ ++#define P9_16(mode) AM33XX_IOPAD(0x084c, mode) /* T14: gpmc_a3 */ ++#define P9_17(mode) AM33XX_IOPAD(0x095c, mode) /* A16: spi0_cs0 */ ++#define P9_18(mode) AM33XX_IOPAD(0x0958, mode) /* B16: spi0_d1 */ ++#define P9_19(mode) AM33XX_IOPAD(0x097c, mode) /* D17: uart1_rtsn */ ++#define P9_20(mode) AM33XX_IOPAD(0x0978, mode) /* D18: uart1_ctsn */ ++#define P9_21(mode) AM33XX_IOPAD(0x0954, mode) /* B17: spi0_d0 */ ++#define P9_22(mode) AM33XX_IOPAD(0x0950, mode) /* A17: spi0_sclk */ ++#define P9_23(mode) AM33XX_IOPAD(0x0844, mode) /* V14: gpmc_a1 */ ++#define P9_24(mode) AM33XX_IOPAD(0x0984, mode) /* D15: uart1_txd */ ++#define P9_25(mode) AM33XX_IOPAD(0x09ac, mode) /* A14: mcasp0_ahclkx */ ++#define P9_26(mode) AM33XX_IOPAD(0x0980, mode) /* D16: uart1_rxd */ ++#define P9_27(mode) AM33XX_IOPAD(0x09a4, mode) /* C13: mcasp0_fsr */ ++#define P9_28(mode) AM33XX_IOPAD(0x099c, mode) /* C12: mcasp0_ahclkr */ ++#define P9_29(mode) AM33XX_IOPAD(0x0994, mode) /* B13: mcasp0_fsx */ ++#define P9_30(mode) AM33XX_IOPAD(0x0998, mode) /* D12: mcasp0_axr0 */ ++#define P9_31(mode) AM33XX_IOPAD(0x0990, mode) /* A13: mcasp0_aclkx */ ++#define P9_41(mode) AM33XX_IOPAD(0x09b4, mode) /* D14: xdma_event_intr1 */ ++#define P9_41A(mode) AM33XX_IOPAD(0x09b4, mode) /* D14: xdma_event_intr1 */ ++#define P9_41B(mode) AM33XX_IOPAD(0x09a8, mode) /* D13: mcasp0_axr1 */ ++#define P9_91(mode) AM33XX_IOPAD(0x09a8, mode) /* D13: mcasp0_axr1 */ ++#define P9_42(mode) AM33XX_IOPAD(0x0964, mode) /* C18: P0_in_PWM0_out */ ++#define P9_42A(mode) AM33XX_IOPAD(0x0964, mode) /* C18: P0_in_PWM0_out */ ++#define P9_42B(mode) AM33XX_IOPAD(0x09a0, mode) /* B12: mcasp0_aclkr */ ++#define P9_92(mode) AM33XX_IOPAD(0x09a0, mode) /* B12: mcasp0_aclkr */ ++ ++#define gpio_P1_02 &gpio2 23 ++#define gpio_P1_04 &gpio2 25 ++#define gpio_P1_06 &gpio0 5 ++#define gpio_P1_08 &gpio0 2 ++#define gpio_P1_10 &gpio0 3 ++#define gpio_P1_12 &gpio0 4 ++#define gpio_P1_20 &gpio0 20 ++#define gpio_P1_26 &gpio0 12 ++#define gpio_P1_28 &gpio0 13 ++#define gpio_P1_29 &gpio3 21 ++#define gpio_P1_30 &gpio1 11 ++#define gpio_P1_31 &gpio3 18 ++#define gpio_P1_32 &gpio1 10 ++#define gpio_P1_33 &gpio3 15 ++#define gpio_P1_34 &gpio0 26 ++#define gpio_P1_35 &gpio2 24 ++#define gpio_P1_36 &gpio3 14 ++#define gpio_P2_01 &gpio1 18 ++#define gpio_P2_02 &gpio1 27 ++#define gpio_P2_03 &gpio0 23 ++#define gpio_P2_04 &gpio1 26 ++#define gpio_P2_05 &gpio0 30 ++#define gpio_P2_06 &gpio1 25 ++#define gpio_P2_07 &gpio0 31 ++#define gpio_P2_08 &gpio1 28 ++#define gpio_P2_09 &gpio0 15 ++#define gpio_P2_10 &gpio1 20 ++#define gpio_P2_11 &gpio0 14 ++#define gpio_P2_17 &gpio2 1 ++#define gpio_P2_18 &gpio1 15 ++#define gpio_P2_19 &gpio0 27 ++#define gpio_P2_20 &gpio2 0 ++#define gpio_P2_22 &gpio1 14 ++#define gpio_P2_24 &gpio1 12 ++#define gpio_P2_25 &gpio1 9 ++#define gpio_P2_27 &gpio1 8 ++#define gpio_P2_28 &gpio3 20 ++#define gpio_P2_29 &gpio0 7 ++#define gpio_P2_30 &gpio3 17 ++#define gpio_P2_31 &gpio0 19 ++#define gpio_P2_32 &gpio3 16 ++#define gpio_P2_33 &gpio1 13 ++#define gpio_P2_34 &gpio3 19 ++#define gpio_P2_35 &gpio2 22 ++ ++#define P1_02(mode) AM33XX_IOPAD(0x08e4, mode) /* R5: lcd_hsync */ ++#define P1_04(mode) AM33XX_IOPAD(0x08ec, mode) /* R6: lcd_ac_bias_en */ ++#define P1_06(mode) AM33XX_IOPAD(0x095c, mode) /* A16: spi0_cs0 */ ++#define P1_08(mode) AM33XX_IOPAD(0x0950, mode) /* A17: spi0_sclk */ ++#define P1_10(mode) AM33XX_IOPAD(0x0954, mode) /* B17: spi0_d0 */ ++#define P1_12(mode) AM33XX_IOPAD(0x0958, mode) /* B16: spi0_d1 */ ++#define P1_20(mode) AM33XX_IOPAD(0x09b4, mode) /* D14: xdma_event_intr1 */ ++#define P1_26(mode) AM33XX_IOPAD(0x0978, mode) /* D18: uart1_ctsn */ ++#define P1_28(mode) AM33XX_IOPAD(0x097c, mode) /* D17: uart1_rtsn */ ++#define P1_29(mode) AM33XX_IOPAD(0x09ac, mode) /* A14: mcasp0_ahclkx */ ++#define P1_30(mode) AM33XX_IOPAD(0x0974, mode) /* E16: uart0_txd */ ++#define P1_31(mode) AM33XX_IOPAD(0x09a0, mode) /* B12: mcasp0_aclkr */ ++#define P1_32(mode) AM33XX_IOPAD(0x0970, mode) /* E15: uart0_rxd */ ++#define P1_33(mode) AM33XX_IOPAD(0x0994, mode) /* B13: mcasp0_fsx */ ++#define P1_34(mode) AM33XX_IOPAD(0x0828, mode) /* T11: gpmc_ad10 */ ++#define P1_35(mode) AM33XX_IOPAD(0x08e8, mode) /* V5: lcd_pclk */ ++#define P1_36(mode) AM33XX_IOPAD(0x0990, mode) /* A13: mcasp0_aclkx */ ++#define P2_01(mode) AM33XX_IOPAD(0x0848, mode) /* U14: gpmc_a2 */ ++#define P2_02(mode) AM33XX_IOPAD(0x086c, mode) /* V17: gpmc_a11 */ ++#define P2_03(mode) AM33XX_IOPAD(0x0824, mode) /* T10: gpmc_ad9 */ ++#define P2_04(mode) AM33XX_IOPAD(0x0868, mode) /* T16: gpmc_a10 */ ++#define P2_05(mode) AM33XX_IOPAD(0x0870, mode) /* T17: gpmc_wait0 */ ++#define P2_06(mode) AM33XX_IOPAD(0x0864, mode) /* U16: gpmc_a9 */ ++#define P2_07(mode) AM33XX_IOPAD(0x0874, mode) /* U17: gpmc_wpn */ ++#define P2_08(mode) AM33XX_IOPAD(0x0878, mode) /* U18: gpmc_be1n */ ++#define P2_09(mode) AM33XX_IOPAD(0x0984, mode) /* D15: uart1_txd */ ++#define P2_10(mode) AM33XX_IOPAD(0x0850, mode) /* R14: gpmc_a4 */ ++#define P2_11(mode) AM33XX_IOPAD(0x0980, mode) /* D16: uart1_rxd */ ++#define P2_17(mode) AM33XX_IOPAD(0x088c, mode) /* V12: gpmc_clk */ ++#define P2_18(mode) AM33XX_IOPAD(0x083c, mode) /* U13: gpmc_ad15 */ ++#define P2_19(mode) AM33XX_IOPAD(0x082c, mode) /* U12: gpmc_ad11 */ ++#define P2_20(mode) AM33XX_IOPAD(0x0888, mode) /* T13: gpmc_csn3 */ ++#define P2_22(mode) AM33XX_IOPAD(0x0838, mode) /* V13: gpmc_ad14 */ ++#define P2_24(mode) AM33XX_IOPAD(0x0830, mode) /* T12: gpmc_ad12 */ ++#define P2_25(mode) AM33XX_IOPAD(0x096c, mode) /* E17: uart0_rtsn */ ++#define P2_27(mode) AM33XX_IOPAD(0x0968, mode) /* E18: uart0_ctsn */ ++#define P2_28(mode) AM33XX_IOPAD(0x09a8, mode) /* D13: mcasp0_axr1 */ ++#define P2_29(mode) AM33XX_IOPAD(0x0964, mode) /* C18: eCAP0_in_PWM0_out */ ++#define P2_30(mode) AM33XX_IOPAD(0x099c, mode) /* C12: mcasp0_ahclkr */ ++#define P2_31(mode) AM33XX_IOPAD(0x09b0, mode) /* A15: xdma_event_intr0 */ ++#define P2_32(mode) AM33XX_IOPAD(0x0998, mode) /* D12: mcasp0_axr0 */ ++#define P2_33(mode) AM33XX_IOPAD(0x0834, mode) /* R12: gpmc_ad13 */ ++#define P2_34(mode) AM33XX_IOPAD(0x09a4, mode) /* C13: mcasp0_fsr */ ++#define P2_35(mode) AM33XX_IOPAD(0x08e0, mode) /* U5: lcd_vsync */ ++ ++#endif +diff -Naur --no-dereference a/include/dt-bindings/clock/microchip,mpfs-clock.h b/include/dt-bindings/clock/microchip,mpfs-clock.h +--- a/include/dt-bindings/clock/microchip,mpfs-clock.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/include/dt-bindings/clock/microchip,mpfs-clock.h 2024-03-28 11:26:09.901017460 -0400 +@@ -44,6 +44,11 @@ + + #define CLK_RTCREF 33 + #define CLK_MSSPLL 34 ++#define CLK_MSSPLL0 34 ++#define CLK_MSSPLL1 35 ++#define CLK_MSSPLL2 36 ++#define CLK_MSSPLL3 37 ++/* 38 is reserved for MSS PLL internals */ + + /* Clock Conditioning Circuitry Clock IDs */ + +diff -Naur --no-dereference a/include/dt-bindings/leds/common.h b/include/dt-bindings/leds/common.h +--- a/include/dt-bindings/leds/common.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/include/dt-bindings/leds/common.h 2024-03-28 11:26:09.901017460 -0400 +@@ -101,6 +101,9 @@ + #define LED_FUNCTION_USB "usb" + #define LED_FUNCTION_WAN "wan" + #define LED_FUNCTION_WLAN "wlan" ++#define LED_FUNCTION_WLAN_2GHZ "wlan-2ghz" ++#define LED_FUNCTION_WLAN_5GHZ "wlan-5ghz" ++#define LED_FUNCTION_WLAN_6GHZ "wlan-6ghz" + #define LED_FUNCTION_WPS "wps" + + #endif /* __DT_BINDINGS_LEDS_H */ +diff -Naur --no-dereference a/include/dt-bindings/mailbox/miv-ihc.h b/include/dt-bindings/mailbox/miv-ihc.h +--- a/include/dt-bindings/mailbox/miv-ihc.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/include/dt-bindings/mailbox/miv-ihc.h 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,17 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++/* ++ * Copyright (c) 2021 Microchip Technology Inc. All rights reserved. ++ */ ++ ++#ifndef __DT_BINDINGS_MIV_IHC_H ++#define __DT_BINDINGS_MIV_IHC_H ++ ++#define IHC_CONTEXT_A 5 ++#define IHC_CONTEXT_B 6 ++ ++#define IHC_HART1_INT 180 ++#define IHC_HART2_INT 179 ++#define IHC_HART3_INT 178 ++#define IHC_HART4_INT 177 ++ ++#endif +diff -Naur --no-dereference a/include/dt-bindings/pinctrl/omap.h b/include/dt-bindings/pinctrl/omap.h +--- a/include/dt-bindings/pinctrl/omap.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/include/dt-bindings/pinctrl/omap.h 2024-03-28 11:26:09.901017460 -0400 +@@ -64,8 +64,12 @@ + #define OMAP3_WKUP_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0x2a00) (val) + #define DM814X_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0x0800) (val) + #define DM816X_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0x0800) (val) +-#define AM33XX_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0x0800) (val) (0) +-#define AM33XX_PADCONF(pa, conf, mux) OMAP_IOPAD_OFFSET((pa), 0x0800) (conf) (mux) ++//Mainline ++//#define AM33XX_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0x0800) (val) (0) ++//#define AM33XX_PADCONF(pa, conf, mux) OMAP_IOPAD_OFFSET((pa), 0x0800) (conf) (mux) ++//BeagleBoard.org (compabitliy with ancient overlays) ++#define AM33XX_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0x0800) (val) ++#define AM33XX_PADCONF(pa, dir, mux) OMAP_IOPAD_OFFSET((pa), 0x0800) ((dir) | (mux)) + + /* + * Macros to allow using the offset from the padconf physical address +diff -Naur --no-dereference a/include/linux/dma/k3-udma-glue.h b/include/linux/dma/k3-udma-glue.h +--- a/include/linux/dma/k3-udma-glue.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/include/linux/dma/k3-udma-glue.h 2024-03-28 11:26:09.901017460 -0400 +@@ -26,6 +26,11 @@ + struct k3_udma_glue_tx_channel *k3_udma_glue_request_tx_chn(struct device *dev, + const char *name, struct k3_udma_glue_tx_channel_cfg *cfg); + ++struct k3_udma_glue_tx_channel * ++k3_udma_glue_request_tx_chn_for_thread_id(struct device *dev, ++ struct k3_udma_glue_tx_channel_cfg *cfg, ++ struct device_node *udmax_np, u32 thread_id); ++ + void k3_udma_glue_release_tx_chn(struct k3_udma_glue_tx_channel *tx_chn); + int k3_udma_glue_push_tx_chn(struct k3_udma_glue_tx_channel *tx_chn, + struct cppi5_host_desc_t *desc_tx, +@@ -109,6 +114,11 @@ + const char *name, + struct k3_udma_glue_rx_channel_cfg *cfg); + ++struct k3_udma_glue_rx_channel * ++k3_udma_glue_request_remote_rx_chn_for_thread_id(struct device *dev, ++ struct k3_udma_glue_rx_channel_cfg *cfg, ++ struct device_node *udmax_np, u32 thread_id); ++ + void k3_udma_glue_release_rx_chn(struct k3_udma_glue_rx_channel *rx_chn); + int k3_udma_glue_enable_rx_chn(struct k3_udma_glue_rx_channel *rx_chn); + void k3_udma_glue_disable_rx_chn(struct k3_udma_glue_rx_channel *rx_chn); +diff -Naur --no-dereference a/include/linux/linux_logo.h b/include/linux/linux_logo.h +--- a/include/linux/linux_logo.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/include/linux/linux_logo.h 2024-03-28 11:26:09.901017460 -0400 +@@ -45,6 +45,7 @@ + extern const struct linux_logo logo_superh_vga16; + extern const struct linux_logo logo_superh_clut224; + extern const struct linux_logo logo_spe_clut224; ++extern const struct linux_logo logo_beagle_clut224; + + extern const struct linux_logo *fb_find_logo(int depth); + #ifdef CONFIG_FB_LOGO_EXTRA +diff -Naur --no-dereference a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h +--- a/include/linux/power/bq27xxx_battery.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/include/linux/power/bq27xxx_battery.h 2024-03-28 11:26:09.901017460 -0400 +@@ -61,7 +61,6 @@ + + struct bq27xxx_device_info { + struct device *dev; +- int id; + enum bq27xxx_chip chip; + u32 opts; + const char *name; +diff -Naur --no-dereference a/include/media/v4l2-mem2mem.h b/include/media/v4l2-mem2mem.h +--- a/include/media/v4l2-mem2mem.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/include/media/v4l2-mem2mem.h 2024-03-28 11:26:09.901017460 -0400 +@@ -84,6 +84,12 @@ + * @last_src_buf: indicate the last source buffer for draining + * @next_buf_last: next capture queud buffer will be tagged as last + * @has_stopped: indicate the device has been stopped ++ * @ignore_cap_streaming: If true, job_ready can be called even if the CAPTURE ++ * queue is not streaming. This allows firmware to ++ * analyze the bitstream header which arrives on the ++ * OUTPUT queue. The driver must implement the job_ready ++ * callback correctly to make sure that the requirements ++ * for actual decoding are met. + * @m2m_dev: opaque pointer to the internal data to handle M2M context + * @cap_q_ctx: Capture (output to memory) queue context + * @out_q_ctx: Output (input from memory) queue context +@@ -106,6 +112,7 @@ + struct vb2_v4l2_buffer *last_src_buf; + bool next_buf_last; + bool has_stopped; ++ bool ignore_cap_streaming; + + /* internal use only */ + struct v4l2_m2m_dev *m2m_dev; +diff -Naur --no-dereference a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h +--- a/include/uapi/linux/input-event-codes.h 2024-01-31 19:19:14.000000000 -0500 ++++ b/include/uapi/linux/input-event-codes.h 2024-03-28 11:26:09.901017460 -0400 +@@ -547,6 +547,7 @@ + #define KEY_FN_S 0x1e3 + #define KEY_FN_B 0x1e4 + #define KEY_FN_RIGHT_SHIFT 0x1e5 ++#define KEY_FN_R 0x1e6 + + #define KEY_BRL_DOT1 0x1f1 + #define KEY_BRL_DOT2 0x1f2 +diff -Naur --no-dereference a/kernel/configs/no_smp.config b/kernel/configs/no_smp.config +--- a/kernel/configs/no_smp.config 1969-12-31 19:00:00.000000000 -0500 ++++ b/kernel/configs/no_smp.config 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,6 @@ ++################################################## ++# NO SMP Config ++################################################## ++ ++CONFIG_SMP=n ++CONFIG_CPUSETS=n +diff -Naur --no-dereference a/kernel/configs/ti_arm64_prune.config b/kernel/configs/ti_arm64_prune.config +--- a/kernel/configs/ti_arm64_prune.config 1969-12-31 19:00:00.000000000 -0500 ++++ b/kernel/configs/ti_arm64_prune.config 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,489 @@ ++# Add config flags here that appear in the multi_v7_defconfig but are not ++# used by a kernel targeting only the currently supported TI EVMs ++ ++# Non-TI Architectures ++CONFIG_ARCH_ACTIONS=n ++CONFIG_ARCH_SUNXI=n ++CONFIG_ARCH_AGILEX=n ++CONFIG_ARCH_ALPINE=n ++CONFIG_ARCH_APPLE=n ++CONFIG_ARCH_BCM=n ++CONFIG_ARCH_BCM2835=n ++CONFIG_ARCH_BCM_IPROC=n ++CONFIG_ARCH_BCMBCA=n ++CONFIG_ARCH_BERLIN=n ++CONFIG_ARCH_BRCMSTB=n ++CONFIG_ARCH_EXYNOS=n ++CONFIG_ARCH_LAYERSCAPE=n ++CONFIG_ARCH_LG1K=n ++CONFIG_ARCH_HISI=n ++CONFIG_ARCH_KEEMBAY=n ++CONFIG_ARCH_MA35=n ++CONFIG_ARCH_MEDIATEK=n ++CONFIG_ARCH_MESON=n ++CONFIG_ARCH_MVEBU=n ++CONFIG_ARCH_NXP=n ++CONFIG_ARCH_MXC=n ++CONFIG_ARCH_NPCM=n ++CONFIG_ARCH_QCOM=n ++CONFIG_ARCH_ROCKCHIP=n ++CONFIG_ARCH_SEATTLE=n ++CONFIG_ARCH_REALTEK=n ++CONFIG_ARCH_RENESAS=n ++CONFIG_ARCH_R8A7795=n ++CONFIG_ARCH_R8A7796=n ++CONFIG_ARCH_S32=n ++CONFIG_ARCH_SPARX5=n ++CONFIG_ARCH_STM32=n ++CONFIG_ARCH_STRATIX10=n ++CONFIG_ARCH_INTEL_SOCFPGA=n ++CONFIG_ARCH_SYNQUACER=n ++CONFIG_ARCH_TEGRA=n ++CONFIG_ARCH_SPRD=n ++CONFIG_ARCH_THUNDER=n ++CONFIG_ARCH_THUNDER2=n ++CONFIG_ARCH_UNIPHIER=n ++CONFIG_ARCH_VEXPRESS=n ++CONFIG_ARCH_VISCONTI=n ++CONFIG_ARCH_XGENE=n ++CONFIG_ARCH_ZX=n ++CONFIG_ARCH_ZYNQMP=n ++CONFIG_ARCH_TEGRA_132_SOC=n ++CONFIG_ARCH_TEGRA_210_SOC=n ++CONFIG_ARCH_TEGRA_186_SOC=n ++ ++CONFIG_QCOM_FALKOR_ERRATUM_1003=n ++CONFIG_QCOM_FALKOR_ERRATUM_1009=n ++CONFIG_QCOM_QDF2400_ERRATUM_0065=n ++CONFIG_QCOM_FALKOR_ERRATUM_E1041=n ++ ++CONFIG_CAVIUM_ERRATUM_22375=n ++CONFIG_CAVIUM_ERRATUM_23144=n ++CONFIG_CAVIUM_ERRATUM_23154=n ++CONFIG_CAVIUM_ERRATUM_27456=n ++CONFIG_CAVIUM_ERRATUM_30115=n ++ ++CONFIG_HISILICON_ERRATUM_161600802=n ++ ++# Disable Errata fixes not relevant for Cortex A53 and Cortext A72 cores. ++# The Socionext Synquacer GICv3 pre-ITS workaround is used on K3 devices ++# as well, thats why its left enabled. ++CONFIG_AMPERE_ERRATUM_AC03_CPU_38=n ++CONFIG_ARM64_ERRATUM_832075=n ++CONFIG_ARM64_ERRATUM_1024718=n ++CONFIG_ARM64_ERRATUM_1418040=n ++CONFIG_ARM64_ERRATUM_1165522=n ++CONFIG_ARM64_ERRATUM_1530923=n ++CONFIG_ARM64_ERRATUM_2441007=n ++CONFIG_ARM64_ERRATUM_1286807=n ++CONFIG_ARM64_ERRATUM_1463225=n ++CONFIG_ARM64_ERRATUM_1542419=n ++CONFIG_ARM64_ERRATUM_1508412=n ++CONFIG_ARM64_ERRATUM_2051678=n ++CONFIG_ARM64_ERRATUM_2077057=n ++CONFIG_ARM64_ERRATUM_2658417=n ++CONFIG_ARM64_ERRATUM_2054223=n ++CONFIG_ARM64_ERRATUM_2067961=n ++CONFIG_ARM64_ERRATUM_2441009=n ++CONFIG_CAVIUM_TX2_ERRATUM_219=n ++CONFIG_FUJITSU_ERRATUM_010001=n ++CONFIG_NVIDIA_CARMEL_CNP_ERRATUM=n ++ ++# Serial ++CONFIG_SERIAL_8250_FSL=n ++CONFIG_SERIAL_8250_DW=n ++CONFIG_SERIAL_AMBA_PL011=n ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=n ++CONFIG_SERIAL_XILINX_PS_UART=n ++CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=n ++ ++CONFIG_ARM_SCPI_PROTOCOL=n ++CONFIG_ARM_SCPI_POWER_DOMAIN=n ++CONFIG_ARM_SCPI_CPUFREQ=n ++CONFIG_SENSORS_ARM_SCPI=n ++CONFIG_COMMON_CLK_SCPI=n ++ ++CONFIG_ARM_MHU=n ++CONFIG_PLATFORM_MHU=n ++ ++CONFIG_ACPI=n ++ ++CONFIG_NUMA=n ++ ++CONFIG_XEN=n ++CONFIG_KVM=n ++ ++CONFIG_ARM_BIG_LITTLE_CPUFREQ=n ++ ++CONFIG_PCI_XGENE=n ++CONFIG_PCI_HISI=n ++CONFIG_PCIE_KIRIN=n ++ ++# DRM ++CONFIG_DRM_NOUVEAU=n ++CONFIG_DRM_I2C_ADV7511=n ++CONFIG_DRM_ETNAVIV=n ++CONFIG_DRM_HISI_HIBMC=n ++CONFIG_DRM_HISI_KIRIN=n ++CONFIG_DRM_MXSFB=n ++CONFIG_DRM_PL111=n ++CONFIG_DRM_LIMA=n ++CONFIG_DRM_PANFROST=n ++ ++# Video ++CONFIG_VGA_ARB=n ++CONFIG_FB_EFI=n ++ ++# V4L2 ++CONFIG_RC_CORE=n ++ ++# Sound ++CONFIG_SND_SPI=n ++CONFIG_SND_SOC_FSL_SAI=n ++CONFIG_SND_SOC_AK4613=n ++CONFIG_SND_SOC_ES7134=n ++CONFIG_SND_SOC_ES7241=n ++CONFIG_SND_SOC_TAS571X=n ++ ++# USB ++CONFIG_USB_MUSB_HDRC=n ++CONFIG_USB_DWC2=n ++CONFIG_USB_CHIPIDEA=n ++CONFIG_USB_ISP1760=n ++CONFIG_USB_HSIC_USB3503=n ++ ++# Generic kernel ++ ++# We recommend to turn off Real-Time group scheduling in the ++# kernel when using systemd. RT group scheduling effectively ++# makes RT scheduling unavailable for most userspace, since it ++# requires explicit assignment of RT budgets to each unit whose ++# processes making use of RT. As there's no sensible way to ++# assign these budgets automatically this cannot really be ++# fixed, and it's best to disable group scheduling hence. ++CONFIG_RT_GROUP_SCHED=n ++ ++# Remove debug features. ++CONFIG_SLUB_DEBUG=n ++ ++# We are not a crash kernel ++CONFIG_CRASH_DUMP=n ++ ++# ARM Scalable Vector Extension (SVE) is available only with ARMv8.2-A ++# and above. Since current TI SoCs are based on ARMv8.0, disable SVE ++CONFIG_ARM64_SVE=n ++ ++# Plan 9 is a distributed resource sharing protocol thats not ++# typically used on TI processors ++CONFIG_NET_9P=n ++ ++# Non-TI hardware vendor specific drivers ++CONFIG_KEYBOARD_CROS_EC=n ++CONFIG_I2C_CROS_EC_TUNNEL=n ++CONFIG_QRTR=n ++CONFIG_SPI_NXP_FLEXSPI=n ++CONFIG_GPIO_ALTERA=n ++CONFIG_GPIO_DWAPB=n ++CONFIG_GPIO_MB86S7X=n ++CONFIG_GPIO_PL061=n ++CONFIG_GPIO_XGENE=n ++CONFIG_POWER_RESET_XGENE=n ++CONFIG_ARM_SP805_WATCHDOG=n ++CONFIG_ARM_SBSA_WATCHDOG=n ++CONFIG_DW_WATCHDOG=n ++CONFIG_MFD_SEC_CORE=n ++CONFIG_REGULATOR_QCOM_SPMI=n ++CONFIG_DRM_MALI_DISPLAY=n ++CONFIG_DRM_RCAR_DW_HDMI=n ++CONFIG_DRM_DW_HDMI_AHB_AUDIO=n ++CONFIG_DRM_DW_HDMI_CEC=n ++CONFIG_FB_SSD1307=n ++CONFIG_MMC_ARMMMCI=n ++CONFIG_MMC_SDHCI_XENON=n ++CONFIG_RTC_DRV_S5M=n ++CONFIG_RTC_DRV_CROS_EC=n ++CONFIG_RTC_DRV_PL031=n ++CONFIG_FSL_EDMA=n ++CONFIG_MV_XOR_V2=n ++CONFIG_PL330_DMA=n ++CONFIG_QCOM_HIDMA_MGMT=n ++CONFIG_QCOM_HIDMA=n ++CONFIG_CHROME_PLATFORMS=n ++CONFIG_CROS_EC=n ++CONFIG_CROS_EC_I2C=n ++CONFIG_CROS_EC_SPI=n ++CONFIG_CROS_EC_CHARDEV=n ++CONFIG_SURFACE_PLATFORMS=n ++CONFIG_COMMON_CLK_S2MPS11=n ++CONFIG_COMMON_CLK_VC5=n ++CONFIG_COMMON_CLK_BD718XX=n ++CONFIG_FSL_ERRATUM_A008585=n ++CONFIG_HISILICON_ERRATUM_161010101=n ++CONFIG_RPMSG_QCOM_GLINK_RPM=n ++CONFIG_SOUNDWIRE_QCOM=n ++CONFIG_EXTCON_USBC_CROS_EC=n ++CONFIG_QCOM_SPMI_ADC5=n ++CONFIG_IIO_CROS_EC_SENSORS_CORE=n ++CONFIG_IIO_CROS_EC_SENSORS=n ++CONFIG_IIO_CROS_EC_LIGHT_PROX=n ++CONFIG_IIO_CROS_EC_BARO=n ++CONFIG_PWM_CROS_EC=n ++CONFIG_SLIM_QCOM_CTRL=n ++CONFIG_SPI_PL022=n ++CONFIG_SLIMBUS=n ++CONFIG_REGMAP_SLIMBUS=n ++CONFIG_SCSI_HISI_SAS=n ++CONFIG_AHCI_CEVA=n ++CONFIG_AHCI_XGENE=n ++CONFIG_AHCI_QORIQ=n ++CONFIG_SATA_SIL24=n ++CONFIG_BCMGENET=n ++CONFIG_SYSTEMPORT=n ++CONFIG_HNS_DSAF=n ++CONFIG_HNS_ENET=n ++CONFIG_HNS3=n ++CONFIG_NET_VENDOR_NVIDIA=n ++CONFIG_NET_VENDOR_RENESAS=n ++CONFIG_NET_VENDOR_SAMSUNG=n ++CONFIG_NET_VENDOR_STMICRO=n ++CONFIG_NET_VENDOR_XILINX=n ++CONFIG_BROADCOM_PHY=n ++CONFIG_BCM54140_PHY=n ++CONFIG_ROCKCHIP_PHY=n ++CONFIG_PCS_XPCS=n ++CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=n ++CONFIG_HW_RANDOM_CN10K=n ++CONFIG_I2C_CADENCE=n ++CONFIG_I2C_DESIGNWARE_SLAVE=n ++CONFIG_I2C_DESIGNWARE_PLATFORM=n ++CONFIG_I2C_RK3X=n ++CONFIG_PINCTRL_MAX77620=n ++CONFIG_DRM_RCAR_USE_LVDS=n ++CONFIG_DRM_RCAR_USE_MIPI_DSI=n ++CONFIG_SND_SOC_FSL_ASRC=n ++CONFIG_SND_SOC_FSL_AUDMIX=n ++CONFIG_SND_SOC_FSL_SSI=n ++CONFIG_SND_SOC_FSL_SPDIF=n ++CONFIG_SND_SOC_FSL_ESAI=n ++CONFIG_SND_SOC_FSL_MICFIL=n ++CONFIG_SND_SOC_IMX_AUDMUX=n ++CONFIG_MMC_SDHCI_OF_DWCMSHC=n ++CONFIG_MMC_SDHCI_CADENCE=n ++CONFIG_MMC_SDHCI_F_SDH30=n ++CONFIG_MMC_DW=n ++CONFIG_MMC_MTK=n ++CONFIG_PCIE_ALTERA=n ++CONFIG_PCI_HOST_THUNDER_PEM=n ++CONFIG_PCI_HOST_THUNDER_ECAM=n ++CONFIG_PCI_MESON=n ++CONFIG_BRCMSTB_GISB_ARB=n ++CONFIG_VEXPRESS_CONFIG=n ++CONFIG_MTD_NAND_DENALI_DT=n ++CONFIG_MTD_NAND_BRCMNAND=n ++CONFIG_B53=n ++CONFIG_NET_DSA_BCM_SF2=n ++CONFIG_CAN_FLEXCAN=n ++CONFIG_SPI_DESIGNWARE=n ++CONFIG_SPI_ROCKCHIP=n ++CONFIG_DRM_HDLCD=n ++CONFIG_DRM_KOMEDA=n ++CONFIG_COMMON_CLK_RK808=n ++CONFIG_COMMON_CLK_XGENE=n ++CONFIG_SOC_BRCMSTB=n ++CONFIG_NET_VENDOR_ALACRITECH=n ++CONFIG_NET_VENDOR_AMAZON=n ++CONFIG_NET_VENDOR_AMD=n ++CONFIG_NET_VENDOR_AQUANTIA=n ++CONFIG_NET_VENDOR_ARC=n ++CONFIG_NET_VENDOR_ASIX=n ++CONFIG_NET_VENDOR_CORTINA=n ++CONFIG_NET_VENDOR_DAVICOM=n ++CONFIG_NET_VENDOR_ENGLEDER=n ++CONFIG_NET_VENDOR_EZCHIP=n ++CONFIG_NET_VENDOR_GOOGLE=n ++CONFIG_NET_VENDOR_HISILICON=n ++CONFIG_NET_VENDOR_LITEX=n ++CONFIG_NET_VENDOR_MICREL=n ++CONFIG_NET_VENDOR_MICROCHIP=n ++CONFIG_NET_VENDOR_MICROSEMI=n ++CONFIG_NET_VENDOR_NATSEMI=n ++CONFIG_NET_VENDOR_NI=n ++CONFIG_NET_VENDOR_QUALCOMM=n ++CONFIG_NET_VENDOR_ROCKER=n ++CONFIG_NET_VENDOR_SEEQ=n ++CONFIG_NET_VENDOR_SMSC=n ++CONFIG_NET_VENDOR_SOCIONEXT=n ++CONFIG_NET_VENDOR_SOLARFLARE=n ++CONFIG_NET_VENDOR_SYNOPSYS=n ++CONFIG_NET_VENDOR_VERTEXCOM=n ++CONFIG_NET_VENDOR_VIA=n ++CONFIG_NET_VENDOR_WANGXUN=n ++CONFIG_NET_VENDOR_WIZNET=n ++CONFIG_NET_VENDOR_BROADCOM=n ++CONFIG_NET_VENDOR_MICROSOFT=n ++CONFIG_NET_VENDOR_FUNGIBLE=n ++CONFIG_NET_VENDOR_CAVIUM=n ++CONFIG_NET_VENDOR_PENSANDO=n ++CONFIG_NET_VENDOR_CADENCE=n ++CONFIG_NET_VENDOR_MELLANOX=n ++CONFIG_NET_VENDOR_NETRONOME=n ++CONFIG_NET_VENDOR_MARVELL=n ++CONFIG_NET_VENDOR_INTEL=n ++CONFIG_NET_VENDOR_HUAWEI=n ++ ++# Serial Power Management Interface (SPMI) has not been used on TI ++# platforms (yet) ++CONFIG_SPMI=n ++ ++# DVB and TV tuner cards are rarely used on TI platforms, if at all ++CONFIG_CXD2880_SPI_DRV=n ++CONFIG_MEDIA_TUNER_E4000=n ++CONFIG_MEDIA_TUNER_FC0011=n ++CONFIG_MEDIA_TUNER_FC0012=n ++CONFIG_MEDIA_TUNER_FC0013=n ++CONFIG_MEDIA_TUNER_FC2580=n ++CONFIG_MEDIA_TUNER_IT913X=n ++CONFIG_MEDIA_TUNER_M88RS6000T=n ++CONFIG_MEDIA_TUNER_MAX2165=n ++CONFIG_MEDIA_TUNER_MC44S803=n ++CONFIG_MEDIA_TUNER_MSI001=n ++CONFIG_MEDIA_TUNER_MT2060=n ++CONFIG_MEDIA_TUNER_MT2063=n ++CONFIG_MEDIA_TUNER_MT20XX=n ++CONFIG_MEDIA_TUNER_MT2131=n ++CONFIG_MEDIA_TUNER_MT2266=n ++CONFIG_MEDIA_TUNER_MXL301RF=n ++CONFIG_MEDIA_TUNER_MXL5005S=n ++CONFIG_MEDIA_TUNER_MXL5007T=n ++CONFIG_MEDIA_TUNER_QM1D1B0004=n ++CONFIG_MEDIA_TUNER_QM1D1C0042=n ++CONFIG_MEDIA_TUNER_QT1010=n ++CONFIG_MEDIA_TUNER_R820T=n ++CONFIG_MEDIA_TUNER_SI2157=n ++CONFIG_MEDIA_TUNER_SIMPLE=n ++CONFIG_MEDIA_TUNER_TDA18212=n ++CONFIG_MEDIA_TUNER_TDA18218=n ++CONFIG_MEDIA_TUNER_TDA18250=n ++CONFIG_MEDIA_TUNER_TDA18271=n ++CONFIG_MEDIA_TUNER_TDA827X=n ++CONFIG_MEDIA_TUNER_TDA8290=n ++CONFIG_MEDIA_TUNER_TDA9887=n ++CONFIG_MEDIA_TUNER_TEA5761=n ++CONFIG_MEDIA_TUNER_TEA5767=n ++CONFIG_MEDIA_TUNER_TUA9001=n ++CONFIG_MEDIA_TUNER_XC2028=n ++CONFIG_MEDIA_TUNER_XC4000=n ++CONFIG_MEDIA_TUNER_XC5000=n ++CONFIG_DVB_M88DS3103=n ++CONFIG_DVB_MXL5XX=n ++CONFIG_DVB_STB0899=n ++CONFIG_DVB_STB6100=n ++CONFIG_DVB_STV090x=n ++CONFIG_DVB_STV0910=n ++CONFIG_DVB_STV6110x=n ++CONFIG_DVB_STV6111=n ++CONFIG_DVB_DRXK=n ++CONFIG_DVB_MN88472=n ++CONFIG_DVB_MN88473=n ++CONFIG_DVB_SI2165=n ++CONFIG_DVB_TDA18271C2DD=n ++CONFIG_DVB_CX24110=n ++CONFIG_DVB_CX24116=n ++CONFIG_DVB_CX24117=n ++CONFIG_DVB_CX24120=n ++CONFIG_DVB_CX24123=n ++CONFIG_DVB_DS3000=n ++CONFIG_DVB_MB86A16=n ++CONFIG_DVB_MT312=n ++CONFIG_DVB_S5H1420=n ++CONFIG_DVB_SI21XX=n ++CONFIG_DVB_STB6000=n ++CONFIG_DVB_STV0288=n ++CONFIG_DVB_STV0299=n ++CONFIG_DVB_STV0900=n ++CONFIG_DVB_STV6110=n ++CONFIG_DVB_TDA10071=n ++CONFIG_DVB_TDA10086=n ++CONFIG_DVB_TDA8083=n ++CONFIG_DVB_TDA8261=n ++CONFIG_DVB_TDA826X=n ++CONFIG_DVB_TS2020=n ++CONFIG_DVB_TUA6100=n ++CONFIG_DVB_TUNER_CX24113=n ++CONFIG_DVB_TUNER_ITD1000=n ++CONFIG_DVB_VES1X93=n ++CONFIG_DVB_ZL10036=n ++CONFIG_DVB_ZL10039=n ++CONFIG_DVB_AF9013=n ++CONFIG_DVB_CX22700=n ++CONFIG_DVB_CX22702=n ++CONFIG_DVB_CXD2820R=n ++CONFIG_DVB_CXD2841ER=n ++CONFIG_DVB_DIB3000MB=n ++CONFIG_DVB_DIB3000MC=n ++CONFIG_DVB_DIB7000M=n ++CONFIG_DVB_DIB7000P=n ++CONFIG_DVB_DIB9000=n ++CONFIG_DVB_DRXD=n ++CONFIG_DVB_EC100=n ++CONFIG_DVB_L64781=n ++CONFIG_DVB_MT352=n ++CONFIG_DVB_NXT6000=n ++CONFIG_DVB_RTL2830=n ++CONFIG_DVB_RTL2832=n ++CONFIG_DVB_RTL2832_SDR=n ++CONFIG_DVB_S5H1432=n ++CONFIG_DVB_SI2168=n ++CONFIG_DVB_SP887X=n ++CONFIG_DVB_STV0367=n ++CONFIG_DVB_TDA10048=n ++CONFIG_DVB_TDA1004X=n ++CONFIG_DVB_ZD1301_DEMOD=n ++CONFIG_DVB_ZL10353=n ++CONFIG_DVB_CXD2880=n ++CONFIG_DVB_STV0297=n ++CONFIG_DVB_TDA10021=n ++CONFIG_DVB_TDA10023=n ++CONFIG_DVB_VES1820=n ++CONFIG_DVB_AU8522_DTV=n ++CONFIG_DVB_AU8522_V4L=n ++CONFIG_DVB_BCM3510=n ++CONFIG_DVB_LG2160=n ++CONFIG_DVB_LGDT3305=n ++CONFIG_DVB_LGDT3306A=n ++CONFIG_DVB_LGDT330X=n ++CONFIG_DVB_MXL692=n ++CONFIG_DVB_NXT200X=n ++CONFIG_DVB_OR51132=n ++CONFIG_DVB_OR51211=n ++CONFIG_DVB_S5H1409=n ++CONFIG_DVB_S5H1411=n ++CONFIG_DVB_DIB8000=n ++CONFIG_DVB_MB86A20S=n ++CONFIG_DVB_S921=n ++CONFIG_DVB_MN88443X=n ++CONFIG_DVB_TC90522=n ++CONFIG_DVB_PLL=n ++CONFIG_DVB_TUNER_DIB0070=n ++CONFIG_DVB_TUNER_DIB0090=n ++CONFIG_DVB_A8293=n ++CONFIG_DVB_AF9033=n ++CONFIG_DVB_ASCOT2E=n ++CONFIG_DVB_ATBM8830=n ++CONFIG_DVB_HELENE=n ++CONFIG_DVB_HORUS3A=n ++CONFIG_DVB_ISL6405=n ++CONFIG_DVB_ISL6421=n ++CONFIG_DVB_ISL6423=n ++CONFIG_DVB_IX2505V=n ++CONFIG_DVB_LGS8GL5=n ++CONFIG_DVB_LGS8GXX=n ++CONFIG_DVB_LNBH25=n ++CONFIG_DVB_LNBH29=n ++CONFIG_DVB_LNBP21=n ++CONFIG_DVB_LNBP22=n ++CONFIG_DVB_M88RS2000=n ++CONFIG_DVB_TDA665x=n ++CONFIG_DVB_DRX39XYJ=n ++CONFIG_DVB_CXD2099=n ++CONFIG_DVB_SP2=n +diff -Naur --no-dereference a/kernel/configs/ti_multi_v7_prune.config b/kernel/configs/ti_multi_v7_prune.config +--- a/kernel/configs/ti_multi_v7_prune.config 1969-12-31 19:00:00.000000000 -0500 ++++ b/kernel/configs/ti_multi_v7_prune.config 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,174 @@ ++# Add config flags here that appear in the multi_v7_defconfig but are not ++# used by a kernel targeting only the currently supported TI EVMs ++ ++# Non-TI Architectures ++CONFIG_ARCH_AIROHA=n ++CONFIG_ARCH_ACTIONS=n ++CONFIG_ARCH_ALPINE=n ++CONFIG_ARCH_ARTPEC=n ++CONFIG_ARCH_ASPEED=n ++CONFIG_ARCH_AT91=n ++CONFIG_ARCH_BCM=n ++CONFIG_ARCH_BCM_CYGNUS=n ++CONFIG_ARCH_BCM_NSP=n ++CONFIG_ARCH_BCM_5301X=n ++CONFIG_ARCH_BCM_281XX=n ++CONFIG_ARCH_BCM_21664=n ++CONFIG_ARCH_BRCMSTB=n ++CONFIG_ARCH_BERLIN=n ++CONFIG_ARCH_DIGICOLOR=n ++CONFIG_ARCH_HIGHBANK=n ++CONFIG_ARCH_HISI=n ++CONFIG_ARCH_HI3xxx=n ++CONFIG_ARCH_HIP01=n ++CONFIG_ARCH_HIP04=n ++CONFIG_ARCH_HIX5HD2=n ++CONFIG_ARCH_HPE=n ++CONFIG_ARCH_HPE_GXP=n ++CONFIG_ARCH_INTEL_SOCFPGA=n ++CONFIG_ARCH_MESON=n ++CONFIG_ARCH_MXC=n ++CONFIG_ARCH_MEDIATEK=n ++CONFIG_ARCH_MILBEAUT=n ++CONFIG_ARCH_QCOM=n ++CONFIG_ARCH_MMP=n ++CONFIG_ARCH_MSM8X60=n ++CONFIG_ARCH_MSM8960=n ++CONFIG_ARCH_MSM8974=n ++CONFIG_ARCH_ROCKCHIP=n ++CONFIG_ARCH_SOCFPGA=n ++CONFIG_ARCH_SPEAR13XX=n ++CONFIG_ARCH_STI=n ++CONFIG_ARCH_EXYNOS=n ++CONFIG_ARCH_SHMOBILE_MULTI=n ++CONFIG_ARCH_EMEV2=n ++CONFIG_ARCH_R7S72100=n ++CONFIG_ARCH_R8A73A4=n ++CONFIG_ARCH_R8A7740=n ++CONFIG_ARCH_R8A7778=n ++CONFIG_ARCH_R8A7779=n ++CONFIG_ARCH_R8A7790=n ++CONFIG_ARCH_R8A7791=n ++CONFIG_ARCH_R8A7793=n ++CONFIG_ARCH_R8A7794=n ++CONFIG_ARCH_RENESAS=n ++CONFIG_ARCH_SH73A0=n ++CONFIG_ARCH_SUNPLUS=y ++CONFIG_ARCH_SUNXI=n ++CONFIG_ARCH_STM32=n ++CONFIG_ARCH_SIRF=n ++CONFIG_ARCH_TEGRA=n ++CONFIG_ARCH_TEGRA_2x_SOC=n ++CONFIG_ARCH_TEGRA_3x_SOC=n ++CONFIG_ARCH_TEGRA_114_SOC=n ++CONFIG_ARCH_TEGRA_124_SOC=n ++CONFIG_ARCH_UNIPHIER=n ++CONFIG_ARCH_U8500=n ++CONFIG_ARCH_VEXPRESS=n ++CONFIG_ARCH_VEXPRESS_TC2_PM=n ++CONFIG_ARCH_WM8850=n ++CONFIG_ARCH_ZYNQ=n ++CONFIG_ARCH_VIRT=n ++CONFIG_ARCH_MVEBU=n ++CONFIG_PLAT_SPEAR=n ++CONFIG_CHROME_PLATFORMS=n ++ ++# Multifunction device drivers ++CONFIG_MFD_AS3711=n ++CONFIG_MFD_AS3722=n ++CONFIG_MFD_ATMEL_FLEXCOM=n ++CONFIG_MFD_ATMEL_HLCDC=n ++CONFIG_MFD_BCM590XX=n ++CONFIG_MFD_AXP20X_I2C=n ++CONFIG_MFD_DA9063=n ++CONFIG_MFD_MAX14577=n ++CONFIG_MFD_MAX77686=n ++CONFIG_MFD_MAX77693=n ++CONFIG_MFD_MAX8907=n ++CONFIG_MFD_MAX8997=n ++CONFIG_MFD_MAX8998=n ++CONFIG_MFD_PM8XXX=n ++CONFIG_MFD_RK808=n ++CONFIG_MFD_RN5T618=n ++CONFIG_MFD_SEC_CORE=n ++CONFIG_MFD_STMPE=n ++ ++# Regulators ++CONFIG_REGULATOR_ACT8865=n ++CONFIG_REGULATOR_DA9210=n ++CONFIG_REGULATOR_FAN53555=n ++CONFIG_REGULATOR_LP872X=n ++CONFIG_REGULATOR_MAX8952=n ++CONFIG_REGULATOR_MAX8973=n ++CONFIG_REGULATOR_PWM=n ++CONFIG_REGULATOR_TPS51632=n ++CONFIG_REGULATOR_TWL4030=n ++ ++# RTC drivers ++CONFIG_RTC_DRV_HYM8563=n ++CONFIG_RTC_DRV_RS5C372=n ++CONFIG_RTC_DRV_BQ32K=n ++CONFIG_RTC_DRV_S35390A=n ++CONFIG_RTC_DRV_RX8581=n ++CONFIG_RTC_DRV_EM3027=n ++ ++# Watchdog Device Drivers ++CONFIG_XILINX_WATCHDOG=n ++CONFIG_DW_WATCHDOG=n ++ ++# GPIO ++CONFIG_GPIO_DWAPB=n ++CONFIG_GPIO_XILINX=n ++CONFIG_GPIO_TPS6586X=n ++ ++# Sound ++CONFIG_SND_ARM=n ++CONFIG_SND_SPI=n ++CONFIG_SND_ATMEL_SOC=n ++CONFIG_SND_SOC_FSL_SAI=n ++CONFIG_SND_SOC_AK4642=n ++CONFIG_SND_SOC_CPCAP=n ++CONFIG_SND_SOC_SGTL5000=n ++CONFIG_SND_SOC_STI_SAS=n ++CONFIG_SND_SOC_WM8978=n ++ ++# DRM ++CONFIG_VGA_ARB=n ++CONFIG_DRM_I2C_ADV7511=n ++CONFIG_DRM_NOUVEAU=n ++CONFIG_DRM_EXYNOS=n ++CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=n ++CONFIG_DRM_NXP_PTN3460=n ++CONFIG_DRM_PARADE_PS8622=n ++CONFIG_DRM_STI=n ++CONFIG_DRM_PANEL_SAMSUNG_LD9040=n ++CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=n ++CONFIG_DRM_DUMB_VGA_DAC=n ++CONFIG_DRM_HISI_KIRIN=n ++CONFIG_DRM_RCAR_LVDS=n ++CONFIG_DRM_FSL_DCU=n ++CONFIG_DRM_SII9234=n ++CONFIG_DRM_MXSFB=n ++CONFIG_DRM_HISI_HIBMC=n ++CONFIG_DRM_ATMEL_HLCDC=n ++CONFIG_DRM_STM=n ++CONFIG_DRM_PANEL_ORISETECH_OTM8009A=n ++CONFIG_DRM_PANEL_RAYDIUM_RM68200=n ++CONFIG_DRM_TOSHIBA_TC358764=n ++CONFIG_DRM_ETNAVIV=n ++CONFIG_DRM_PL111=n ++CONFIG_DRM_LIMA=n ++CONFIG_DRM_PANFROST=n ++ ++# Video ++CONFIG_LCD_CLASS_DEVICE=n ++CONFIG_FB_EFI=n ++CONFIG_FB_SIMPLE=n ++CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=n ++CONFIG_FB_ARMCLCD=n ++CONFIG_XEN_FBDEV_FRONTEND=n ++ ++# USB ++CONFIG_USB_DWC2=n ++CONFIG_USB_CHIPIDEA=n ++CONFIG_USB_ISP1760=n +diff -Naur --no-dereference a/kernel/configs/ti_rt.config b/kernel/configs/ti_rt.config +--- a/kernel/configs/ti_rt.config 1969-12-31 19:00:00.000000000 -0500 ++++ b/kernel/configs/ti_rt.config 2024-03-28 11:26:09.901017460 -0400 +@@ -0,0 +1,165 @@ ++################################################## ++# Real Time Linux Configs ++################################################## ++ ++CONFIG_EXPERT=y ++CONFIG_PREEMPT=y ++CONFIG_PREEMPT_RT=y ++ ++# max out the kernel's tick ++# ++# Ideally this is a balance. Increasing this means we ++# spend more time in the scheduler deciding what we ++# should do and less time on doing it however this ++# also minimizes the time spent running a low-priority ++# task while a real-time priority task is awake ++CONFIG_HZ_1000=y ++CONFIG_HZ=1000 ++ ++# omit scheduling ticks for CPUs with a single task ++# ++# If a CPU has only one runnable task there is little ++# need to contiguously interrupt it as there is no other ++# task for it to switch to. This comes at the cost of having ++# to offload the CPU's RCU callbacks to another CPU with ++# an active tick. ++# ++# For workloads with many short-lived tasks HZ_PERIODIC may ++# be the better selection as adaptive-tick modes does not ++# come without tradeoffs. For example the user-to kernel ++# transitions are slightly more expensive ++CONFIG_NO_HZ_FULL=y ++CONFIG_CONTEXT_TRACKING_USER=y ++ ++# track our RCU callbacks ++# ++# there are situations in which idle CPUs cannot enter ++# a dynctick or adaptive-tick mode, the most common reason ++# being when a CPU has RCU callbacks pending. We can avoid ++# this by processing all RCU callbacks in the "rcuo" kthread ++# that we can 'boost' to real-time priority to prevent RCU ++# stalls in real-time heavy workloads. ++CONFIG_RCU_NOCB_CPU=y ++CONFIG_RCU_NOCB_CPU_DEFAULT_ALL=y ++CONFIG_RCU_NOCB_CPU_CB_BOOST=y ++ ++# memory management tuning ++# ++# The SLUB allocator (default allocator used by the kernel) ++# uses per-cpu caches to accelerate allocation and freeing of ++# objects local to that processor. This comes at the cost of ++# more indeterminism when freeing. Remove this to remove jitter ++CONFIG_SLUB_CPU_PARTIAL=n ++ ++# RCU system tuning ++# ++# The scheduler heavily utilizes the RCU subsystem to avoid ++# large amounts of locking that would be needed otherwise. ++# Removing this is showing to improve the am62x latency numbers ++# using stress-ng and cyclictest. ++CONFIG_RCU_TRACE=n ++ ++# remove have kmemleak support ++# ++# Even-though the kmemleak detector is disabled, removing it ++# completely from the build is showing improvements for the ++# am62x latency numbers when monitoring with cyclictest and ++# stress-ng to generate a synthetic background load. ++CONFIG_HAVE_DEBUG_KMEMLEAK=n ++ ++# Disable debug features ++ ++# CoreSight debug and trace drivers are not typically used in ++# production. Keep them disabled by default. Users can enable ++# when debugging is needed. ++CONFIG_CORESIGHT=n ++ ++# Remove support for symbolic crash dumps. These are useful ++# while debugging and not must have for production. This also ++# helps reduce kernel size. ++CONFIG_KALLSYMS=n ++ ++# Disable profiling support. Not needed on a production system. ++CONFIG_PROFILING=n ++ ++# Disable support for performance events. These are used only ++# for development and debug. Not needed on production system. ++CONFIG_PERF_EVENTS=n ++ ++# Disable eBPF support which is typically used for tracing and ++# profiling. This prevents users from loading eBPF programs ++# but BPF usage within the kernel should still work. Disabling ++# JIT compiler will slow down packet filtering. ++CONFIG_BPF_SYSCALL=n ++CONFIG_BPF_JIT=n ++ ++# Fine granularity IRQ time accounting is not needed on a ++# production system. ++CONFIG_IRQ_TIME_ACCOUNTING=n ++ ++# Disable ARMv8.1+ architecture featurres. TI processors are based ++# on ARMv8.0, and these feaures are not applicable. If enabled ++# they increase worst case latency from 41 usec to 83 usec when ++# tested on AM62x silicon with 1 hour cyclictest. ++CONFIG_ARM64_HW_AFDBM=n ++CONFIG_ARM64_PAN=n ++CONFIG_ARM64_USE_LSE_ATOMICS=n ++CONFIG_ARM64_RAS_EXTN=n ++CONFIG_ARM64_CNP=n ++CONFIG_ARM64_PTR_AUTH=n ++CONFIG_ARM64_AMU_EXTN=n ++CONFIG_ARM64_TLB_RANGE=n ++CONFIG_ARM64_BTI=n ++CONFIG_ARM64_E0PD=n ++ ++# Disable group scheduling. We already disable RT_GROUP_SCHEDULING since ++# there is no way to meaningfully use it (see kernel/configs/ti_arm64_prune.config). ++# Disable group scheduling as such on RT kernel - the main focus anyway ++# is on RT tasks there. ++CONFIG_SCHED_AUTOGROUP=n ++ ++# Disable symmetric multi-threading scheduler. Its not used on ARM64 ++CONFIG_SCHED_SMT=n ++ ++# Kernel stack base address randomization helps frustate attacks that depend on ++# stack address determinism. But it has an impact on RT latency. Using 1 hour ++# cyclictest on AM62x, it was found to increase worst case latency from 50 usecs ++# to 69 usecs. For RT kernel alone, be biased towards better latency over extra ++# security. ++CONFIG_RANDOMIZE_KSTACK_OFFSET=n ++ ++# Kernel can apply read-only permissions to linear aliases of VM areas. This ++# provides extra layer of protection against advertent/inadvertent modification ++# of read-only data through the linear alias. While its a useful security ++# feature, it has performance and RT latency impact. When testing on AM62x ++# hardware using cyclictest running for 1 hour, the worst case latency increased ++# from 50 usecs to 58 usecs when this feature was enabled. ++CONFIG_RODATA_FULL_DEFAULT_ENABLED=n ++ ++# Kernel page table isolation (KAISER) unmaps kernel page tables when in EL0 ++# to mitigate speculation attacks that enable privilege bypass. Note that CPUs ++# used on K3 SoCs are not impacted by meltdown vulnerability (CVE-2017-5754). ++# Using a 6 hour cyclictest, enabling KAISER was seen to increase worst case ++# latency by about 20 usecs (increase from 50 usecs to 70 usecs on AM62x hardware ++# using cutdown configuration designed to minimizeRT latency) ++CONFIG_UNMAP_KERNEL_AT_EL0=n ++ ++# Disable control groups which are not minimum required by systemd and docker. ++# These can be enabled as per need of end application. ++# ++# Keeping device control group enabled as docker example does not start without ++# it. ++# ++# Having these enabled has an impact on RT latency. Using AM62x, using cyclictest, ++# a 40 usecs latency impact was seen (worst case latency went from 50 usecs to 90 ++# usecs) ++CONFIG_MEMCG=n ++CONFIG_BLK_CGROUP=n ++CONFIG_CGROUP_SCHED=n ++CONFIG_CGROUP_PIDS=n ++CONFIG_CGROUP_FREEZER=n ++CONFIG_CGROUP_HUGETLB=n ++CONFIG_CPUSETS=n ++CONFIG_CGROUP_CPUACCT=n ++CONFIG_CGROUP_PERF=n ++CONFIG_CGROUP_BPF=n +diff -Naur --no-dereference a/MAINTAINERS b/MAINTAINERS +--- a/MAINTAINERS 2024-01-31 19:19:14.000000000 -0500 ++++ b/MAINTAINERS 2024-03-28 11:26:09.893017428 -0400 +@@ -5110,7 +5110,7 @@ + L: linux-media@vger.kernel.org + S: Maintained + F: Documentation/devicetree/bindings/media/coda.yaml +-F: drivers/media/platform/chips-media/ ++F: drivers/media/platform/chips-media/coda + + CODE OF CONDUCT + M: Greg Kroah-Hartman +@@ -8988,6 +8988,13 @@ + F: drivers/staging/greybus/spi.c + F: drivers/staging/greybus/spilib.c + ++GREYBUS BEAGLEPLAY DRIVERS ++M: Ayush Singh ++L: greybus-dev@lists.linaro.org (moderated for non-subscribers) ++S: Maintained ++F: Documentation/devicetree/bindings/net/ti,cc1352p7.yaml ++F: drivers/greybus/gb-beagleplay.c ++ + GREYBUS SUBSYSTEM + M: Johan Hovold + M: Alex Elder +@@ -21572,6 +21579,13 @@ + F: drivers/media/i2c/ds90* + F: include/media/i2c/ds90* + ++TI J721E CSI2RX DRIVER ++M: Jai Luthra ++L: linux-media@vger.kernel.org ++S: Maintained ++F: Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml ++F: drivers/media/platform/ti/j721e-csi2rx/ ++ + TI KEYSTONE MULTICORE NAVIGATOR DRIVERS + M: Nishanth Menon + M: Santosh Shilimkar +@@ -23203,6 +23217,14 @@ + F: include/trace/events/watchdog.h + F: include/uapi/linux/watchdog.h + ++WAVE5 VPU CODEC DRIVER ++M: Nas Chung ++M: Jackson Lee ++L: linux-media@vger.kernel.org ++S: Maintained ++F: Documentation/devicetree/bindings/media/cnm,wave5.yaml ++F: drivers/media/platform/chips-media/wave5/ ++ + WHISKEYCOVE PMIC GPIO DRIVER + M: Kuppuswamy Sathyanarayanan + L: linux-gpio@vger.kernel.org +diff -Naur --no-dereference a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +--- a/net/hsr/hsr_device.c 2024-01-31 19:19:14.000000000 -0500 ++++ b/net/hsr/hsr_device.c 2024-03-28 11:26:09.901017460 -0400 +@@ -291,7 +291,7 @@ + + skb = hsr_init_skb(master); + if (!skb) { +- WARN_ONCE(1, "HSR: Could not send supervision frame\n"); ++ netdev_warn_once(master->dev, "HSR: Could not send supervision frame\n"); + return; + } + +@@ -338,7 +338,7 @@ + + skb = hsr_init_skb(master); + if (!skb) { +- WARN_ONCE(1, "PRP: Could not send supervision frame\n"); ++ netdev_warn_once(master->dev, "PRP: Could not send supervision frame\n"); + return; + } + +diff -Naur --no-dereference a/README.md b/README.md +--- a/README.md 1969-12-31 19:00:00.000000000 -0500 ++++ b/README.md 2024-03-28 11:26:09.893017428 -0400 +@@ -0,0 +1,3 @@ ++# Gitlab CI ++ ++Job Status: https://git.beagleboard.org/beagleboard/linux/-/jobs +diff -Naur --no-dereference a/scripts/package/builddeb b/scripts/package/builddeb +--- a/scripts/package/builddeb 2024-01-31 19:19:14.000000000 -0500 ++++ b/scripts/package/builddeb 2024-03-28 11:26:09.901017460 -0400 +@@ -60,6 +60,7 @@ + # Only some architectures with OF support have this target + if is_enabled CONFIG_OF_EARLY_FLATTREE && [ -d "${srctree}/arch/${SRCARCH}/boot/dts" ]; then + ${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install ++ ${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/boot/dtbs/${KERNELRELEASE}" dtbs_install + fi + + ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install +diff -Naur --no-dereference a/tools/testing/selftests/net/forwarding/ethtool_mm.sh b/tools/testing/selftests/net/forwarding/ethtool_mm.sh +--- a/tools/testing/selftests/net/forwarding/ethtool_mm.sh 2024-01-31 19:19:14.000000000 -0500 ++++ b/tools/testing/selftests/net/forwarding/ethtool_mm.sh 2024-03-28 11:26:09.901017460 -0400 +@@ -25,6 +25,10 @@ + local after= + local delta= + ++ if [ ${has_pmac_stats[$if]} = false ]; then ++ src="aggregate" ++ fi ++ + before=$(ethtool_std_stats_get $if "eth-mac" "FramesTransmittedOK" $src) + + $MZ $if -q -c $num_pkts -p 64 -b bcast -t ip -R $PREEMPTIBLE_PRIO +@@ -155,15 +159,48 @@ + manual_failed_verification $h2 $h1 + } + ++smallest_supported_add_frag_size() ++{ ++ local iface=$1 ++ local rx_min_frag_size= ++ ++ rx_min_frag_size=$(ethtool --json --show-mm $iface | \ ++ jq '.[]."rx-min-frag-size"') ++ ++ if [ $rx_min_frag_size -le 60 ]; then ++ echo 0 ++ elif [ $rx_min_frag_size -le 124 ]; then ++ echo 1 ++ elif [ $rx_min_frag_size -le 188 ]; then ++ echo 2 ++ elif [ $rx_min_frag_size -le 252 ]; then ++ echo 3 ++ else ++ echo "$iface: RX min frag size $rx_min_frag_size cannot be advertised over LLDP" ++ exit 1 ++ fi ++} ++ ++expected_add_frag_size() ++{ ++ local iface=$1 ++ local requested=$2 ++ local min=$(smallest_supported_add_frag_size $iface) ++ ++ [ $requested -le $min ] && echo $min || echo $requested ++} ++ + lldp_change_add_frag_size() + { + local add_frag_size=$1 ++ local pattern= + + lldptool -T -i $h1 -V addEthCaps addFragSize=$add_frag_size >/dev/null + # Wait for TLVs to be received + sleep 2 +- lldptool -i $h2 -t -n -V addEthCaps | \ +- grep -q "Additional fragment size: $add_frag_size" ++ pattern=$(printf "Additional fragment size: %d" \ ++ $(expected_add_frag_size $h1 $add_frag_size)) ++ lldptool -i $h2 -t -n -V addEthCaps | grep -q "$pattern" + } + + lldp() +@@ -284,6 +321,13 @@ + echo "SKIP: $netif does not support MAC Merge" + exit $ksft_skip + fi ++ ++ if check_ethtool_pmac_std_stats_support $netif eth-mac; then ++ has_pmac_stats[$netif]=true ++ else ++ has_pmac_stats[$netif]=false ++ echo "$netif does not report pMAC statistics, falling back to aggregate" ++ fi + done + + trap cleanup EXIT +diff -Naur --no-dereference a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh +--- a/tools/testing/selftests/net/forwarding/lib.sh 2024-01-31 19:19:14.000000000 -0500 ++++ b/tools/testing/selftests/net/forwarding/lib.sh 2024-03-28 11:26:09.901017460 -0400 +@@ -148,6 +148,15 @@ + fi + } + ++check_ethtool_pmac_std_stats_support() ++{ ++ local dev=$1; shift ++ local grp=$1; shift ++ ++ [ 0 -ne $(ethtool --json -S $dev --all-groups --src pmac 2>/dev/null \ ++ | jq ".[].\"$grp\" | length") ] ++} ++ + check_locked_port_support() + { + if ! bridge -d link show | grep -q " locked"; then diff --git a/linux/linux-5.10.defconfig b/linux/linux-6.6.defconfig similarity index 94% rename from linux/linux-5.10.defconfig rename to linux/linux-6.6.defconfig index 465ccfa3..22daecc1 100644 --- a/linux/linux-5.10.defconfig +++ b/linux/linux-6.6.defconfig @@ -4,6 +4,7 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_JIT=y CONFIG_PREEMPT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y @@ -14,21 +15,13 @@ CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y -CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_IPC_NS is not set # CONFIG_PID_NS is not set # CONFIG_NET_NS is not set CONFIG_SCHED_AUTOGROUP=y -# CONFIG_SYSFS_SYSCALL is not set -# CONFIG_RSEQ is not set -CONFIG_EMBEDDED=y # CONFIG_PERF_EVENTS is not set -# CONFIG_SLUB_DEBUG is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_PROFILING=y -CONFIG_OMAP_RESET_CLOCKS=y CONFIG_SOC_AM33XX=y CONFIG_SOC_HAS_OMAP2_SDRC=y CONFIG_SWP_EMULATE=y @@ -60,6 +53,8 @@ CONFIG_PARTITION_ADVANCED=y # CONFIG_EFI_PARTITION is not set # CONFIG_MQ_IOSCHED_DEADLINE is not set # CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_SLAB_FREELIST_RANDOM=y +# CONFIG_COMPAT_BRK is not set CONFIG_CMA=y CONFIG_NET=y CONFIG_PACKET=y @@ -114,12 +109,10 @@ CONFIG_EXTRA_FIRMWARE_DIR="firmware" CONFIG_FW_LOADER_USER_HELPER=y CONFIG_OMAP_INTERCONNECT=y CONFIG_OMAP_OCP2SCP=y -CONFIG_SIMPLE_PM_BUS=y CONFIG_CONNECTOR=y CONFIG_OF_OVERLAY=y CONFIG_SRAM=y CONFIG_EEPROM_AT24=y -CONFIG_BEAGLEBONE_PINMUX_HELPER=y CONFIG_SCSI=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y @@ -131,7 +124,6 @@ CONFIG_TUN=m # CONFIG_NET_VENDOR_AMAZON is not set # CONFIG_NET_VENDOR_AQUANTIA is not set # CONFIG_NET_VENDOR_ARC is not set -# CONFIG_NET_VENDOR_AURORA is not set # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_CADENCE is not set # CONFIG_NET_VENDOR_CAVIUM is not set @@ -148,9 +140,9 @@ CONFIG_TUN=m # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MICROCHIP is not set # CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_NI is not set # CONFIG_NET_VENDOR_NATSEMI is not set # CONFIG_NET_VENDOR_NETRONOME is not set -# CONFIG_NET_VENDOR_NI is not set # CONFIG_NET_VENDOR_PENSANDO is not set # CONFIG_NET_VENDOR_QUALCOMM is not set # CONFIG_NET_VENDOR_RENESAS is not set @@ -203,9 +195,8 @@ CONFIG_I2C_GPIO=y CONFIG_SPI=y CONFIG_SPI_OMAP24XX=y CONFIG_SPI_SPIDEV=y +# CONFIG_PTP_1588_CLOCK is not set CONFIG_PINCTRL_SINGLE=y -CONFIG_GPIO_SYSFS=y -CONFIG_GPIO_OF_HELPER=y CONFIG_GPIO_GENERIC_PLATFORM=y CONFIG_GPIO_SYSCON=y CONFIG_POWER_RESET=y @@ -263,7 +254,6 @@ CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_ONESHOT=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_GPIO=y CONFIG_LEDS_TRIGGER_DEFAULT_ON=y CONFIG_LEDS_TRIGGER_TRANSIENT=y CONFIG_LEDS_TRIGGER_PATTERN=y @@ -296,7 +286,6 @@ CONFIG_OMAP_USB2=y CONFIG_TI_PIPE3=y CONFIG_F2FS_FS=y # CONFIG_F2FS_FS_XATTR is not set -# CONFIG_MANDATORY_FILE_LOCKING is not set CONFIG_FANOTIFY=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y @@ -321,7 +310,4 @@ CONFIG_CMA_SIZE_MBYTES=48 CONFIG_PRINTK_TIME=y CONFIG_DEBUG_FS=y CONFIG_PANIC_TIMEOUT=10 -# CONFIG_SCHED_DEBUG is not set -# CONFIG_DEBUG_PREEMPT is not set -# CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/linux/update-kernel-patch.sh b/linux/update-kernel-patch.sh index 2241ec2b..d0dafed1 100755 --- a/linux/update-kernel-patch.sh +++ b/linux/update-kernel-patch.sh @@ -11,7 +11,7 @@ update_kernel_patch() { local OUTPUT_PATCH=$3 local ORIGINAL_DIFF=patch-$PATCH_VERSION.diff - local ORIGINAL_DIFF_XZ=$ORIGINAL_DIFF.xz + local ORIGINAL_DIFF_XZ=$ORIGINAL_DIFF.gz local KERNEL_TARBALL=linux-$KERNEL_VERSION.tar.xz # Work in a temporary directory @@ -21,22 +21,8 @@ update_kernel_patch() { echo "Downloading files..." - local RCN_PATCH_URL - local KERNEL_URL - - case $KERNEL_VERSION in - 5*) - RCN_PATCH_URL=http://rcn-ee.net/deb/bookworm-armhf/v$PATCH_VERSION/$ORIGINAL_DIFF_XZ - KERNEL_URL=https://www.kernel.org/pub/linux/kernel/v5.x/$KERNEL_TARBALL - ;; - 4*) - RCN_PATCH_URL=http://rcn-ee.net/deb/bullseye-armhf/v$PATCH_VERSION/$ORIGINAL_DIFF_XZ - KERNEL_URL=https://www.kernel.org/pub/linux/kernel/v4.x/$KERNEL_TARBALL - ;; - *) - echo "Unexpected kernel version: $KERNEL_VERSION" - exit 1 - esac + RCN_PATCH_URL=http://rcn-ee.net/deb/sid-armhf/v$PATCH_VERSION/$ORIGINAL_DIFF_XZ + KERNEL_URL=https://www.kernel.org/pub/linux/kernel/v6.x/$KERNEL_TARBALL # Download the master patch file for the RCN kernel wget $RCN_PATCH_URL @@ -50,7 +36,7 @@ update_kernel_patch() { tar -x -f $KERNEL_TARBALL && mv linux-$KERNEL_VERSION b # Expand the "git" style patch - unxz $ORIGINAL_DIFF_XZ + gunzip $ORIGINAL_DIFF_XZ # Make a git repo and apply the "git" style patch echo "Creating temporary git repo to extract RCN patch..." @@ -74,8 +60,6 @@ update_kernel_patch() { return 0 } -#update_kernel_patch 4.19.120-bone50 4.19.120 0001-rcn-linux-4.19.120-bone50.patch -#update_kernel_patch 5.4.115-bone52 5.4.115 0001-rcn-linux-5.4.115-bone52.patch -update_kernel_patch 5.10.120-ti-r46 5.10.120 0001-rcn-linux-5.10.120-ti-r46.patch +update_kernel_patch 6.6.15-ti-arm32-r1 6.6.15 0001-rcn-linux-6.6.15-ti-arm32-r1.patch echo "Updated patches. Now rebuild the linux kernel." diff --git a/mix.exs b/mix.exs index ed05836b..47d44dc2 100644 --- a/mix.exs +++ b/mix.exs @@ -66,9 +66,9 @@ defmodule NervesSystemC2.MixProject do defp deps do [ - {:nerves, "~> 1.6.0 or ~> 1.7.15 or ~> 1.8.0", runtime: false}, - {:nerves_system_br, "1.20.3", runtime: false}, - {:nerves_toolchain_armv7_nerves_linux_gnueabihf, "~> 1.4.2", runtime: false}, + {:nerves, "~> 1.6.0 or ~> 1.7.15 or ~> 1.8", runtime: false}, + {:nerves_system_br, "1.27.1", runtime: false}, + {:nerves_toolchain_armv7_nerves_linux_gnueabihf, "~> 13.2.0", runtime: false}, {:nerves_system_linter, "~> 0.4", only: [:dev, :test], runtime: false}, {:ex_doc, "~> 0.22", only: :docs, runtime: false} ] @@ -108,7 +108,7 @@ defmodule NervesSystemC2.MixProject do "uboot", "busybox.fragment", "CHANGELOG.md", - "fwup-revert.conf", + "fwup-ops.conf", "fwup.conf", "LICENSE", "mix.exs", diff --git a/mix.lock b/mix.lock index 4ff35206..89fea3e2 100644 --- a/mix.lock +++ b/mix.lock @@ -1,15 +1,16 @@ %{ - "castore": {:hex, :castore, "0.1.19", "a2c3e46d62b7f3aa2e6f88541c21d7400381e53704394462b9fd4f06f6d42bb6", [:mix], [], "hexpm", "e96e0161a5dc82ef441da24d5fa74aefc40d920f3a6645d15e1f9f3e66bb2109"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.26", "f4291134583f373c7d8755566122908eb9662df4c4b63caa66a0eabe06569b0a", [:mix], [], "hexpm", "48d460899f8a0c52c5470676611c01f64f3337bad0b26ddab43648428d94aabc"}, - "elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"}, - "ex_doc": {:hex, :ex_doc, "0.28.4", "001a0ea6beac2f810f1abc3dbf4b123e9593eaa5f00dd13ded024eae7c523298", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bf85d003dd34911d89c8ddb8bda1a958af3471a274a4c2150a9c01c78ac3f8ed"}, - "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, - "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, - "nerves": {:hex, :nerves, "1.8.0", "2735cda2037985411ede03c59937e9cb222f8990d5540e1a0e1ec77db96618cc", [:make, :mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "878c82ec079cf75ea48229ce802d2c2edf24bee60c17c33e477b18f83f7a49e1"}, - "nerves_system_br": {:hex, :nerves_system_br, "1.20.3", "8f3b69f9458b4b71ca2db0cd40c8894ea7705f15097e7111ad37f631edea4c16", [:mix], [], "hexpm", "c5a7b781455b3b982132299b0975ee3aade345cc51dc68a50e6b7bb556badbd5"}, + "castore": {:hex, :castore, "1.0.6", "ffc42f110ebfdafab0ea159cd43d31365fa0af0ce4a02ecebf1707ae619ee727", [:mix], [], "hexpm", "374c6e7ca752296be3d6780a6d5b922854ffcc74123da90f2f328996b962d33a"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, + "elixir_make": {:hex, :elixir_make, "0.8.3", "d38d7ee1578d722d89b4d452a3e36bcfdc644c618f0d063b874661876e708683", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "5c99a18571a756d4af7a4d89ca75c28ac899e6103af6f223982f09ce44942cc9"}, + "ex_doc": {:hex, :ex_doc, "0.32.1", "21e40f939515373bcdc9cffe65f3b3543f05015ac6c3d01d991874129d173420", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "5142c9db521f106d61ff33250f779807ed2a88620e472ac95dc7d59c380113da"}, + "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, + "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.5", "e0ff5a7c708dda34311f7522a8758e23bfcd7d8d8068dc312b5eb41c6fd76eba", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "94d2e986428585a21516d7d7149781480013c56e30c6a233534bedf38867a59a"}, + "nerves": {:hex, :nerves, "1.10.5", "9c4296a5fd9c48858a92b17ae52cfcf1bc9acfefdc2da5c10ec79e4c139ecaec", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "a1309b6c56e2797f7514e89afc61b7c06803f359e94b00ac006bef4e611d95e9"}, + "nerves_system_br": {:hex, :nerves_system_br, "1.27.1", "91e87e12f05661b7b2130990bbf7c43b3bbee28dfc9de655041255415d0cae52", [:mix], [], "hexpm", "2d0b600a630b3645fdbbacbea9d1ad83e32141e18ed446f6b360da5c0055c647"}, "nerves_system_linter": {:hex, :nerves_system_linter, "0.4.0", "81e9a6f5018fe5fb67d7b43a04dca36156f62b55b5554eb2fa3964d3889d09cd", [:mix], [], "hexpm", "b5bd8480ce7a6317f4601ff41fd2f594bdf76aff0bdf6dcfac571c3fa1ec5f82"}, - "nerves_toolchain_armv7_nerves_linux_gnueabihf": {:hex, :nerves_toolchain_armv7_nerves_linux_gnueabihf, "1.4.3", "ff5b8fed2a71daea7ac07a5a0a6ecec7a4985d2a617a89ab073591d441d9cda4", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.8.4", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm", "ffefca61b7282a5a10032e61b6dab6758d24eee732c5d8c16fe6aada52dd099a"}, - "nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.8.5", "f2dfd6e3b5f85889561b9f00c71510eea87c3d05760d20780285deb3c29ca212", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}], "hexpm", "2f65b1866f034054f3d61ee672b6d02f4de1d0b40bef74f49527b98ab46a39fc"}, - "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, + "nerves_toolchain_armv7_nerves_linux_gnueabihf": {:hex, :nerves_toolchain_armv7_nerves_linux_gnueabihf, "13.2.0", "48305b5ba2ec41d2f9bfd0997d6bb6e8a9f5358146baa58fc64887bfe2d38ccd", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.10.0", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm", "7a43b14eb4ec90f36acf36a42ce42c1d69c280b90eea7ab9965e00db3ee6cbf7"}, + "nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.10.0", "c6b35377a0b7a93633a8673a788f1580fe1fa06083374b0e4df36da65828d2ef", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}], "hexpm", "e4ae1a2b84de3502ecac195765819be0ce2834eb276553163a7c03133f1760f1"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"} } diff --git a/nerves_defconfig b/nerves_defconfig index 6f34b09a..115df5ad 100644 --- a/nerves_defconfig +++ b/nerves_defconfig @@ -1,22 +1,22 @@ BR2_arm=y BR2_cortex_a8=y BR2_ARM_FPU_VFPV3=y -BR2_TAR_OPTIONS="--no-same-owner" -BR2_BACKUP_SITE="http://dl.nerves-project.org" -BR2_ENABLE_DEBUG=y -BR2_OPTIMIZE_2=y -BR2_GLOBAL_PATCH_DIR="${BR2_EXTERNAL_NERVES_PATH}/patches" -BR2_REPRODUCIBLE=y BR2_TOOLCHAIN_EXTERNAL=y BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y -BR2_TOOLCHAIN_EXTERNAL_URL="https://github.com/nerves-project/toolchains/releases/download/v1.4.2/nerves_toolchain_armv7_nerves_linux_gnueabihf-linux_x86_64-1.4.2-6A1DC92.tar.xz" +BR2_TOOLCHAIN_EXTERNAL_URL="https://github.com/nerves-project/toolchains/releases/download/v13.2.0/nerves_toolchain_armv7_nerves_linux_gnueabihf-linux_${shell uname -m}-13.2.0-BE3EA83.tar.xz" BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="armv7-nerves-linux-gnueabihf" -BR2_TOOLCHAIN_EXTERNAL_GCC_10=y -BR2_TOOLCHAIN_EXTERNAL_HEADERS_4_14=y +BR2_TOOLCHAIN_EXTERNAL_HEADERS_5_4=y BR2_TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC=y # BR2_TOOLCHAIN_EXTERNAL_INET_RPC is not set BR2_TOOLCHAIN_EXTERNAL_CXX=y +BR2_TOOLCHAIN_EXTERNAL_FORTRAN=y +BR2_TOOLCHAIN_EXTERNAL_OPENMP=y +BR2_TAR_OPTIONS="--no-same-owner" +BR2_BACKUP_SITE="http://dl.nerves-project.org" +BR2_ENABLE_DEBUG=y +BR2_GLOBAL_PATCH_DIR="${BR2_EXTERNAL_NERVES_PATH}/patches" +BR2_REPRODUCIBLE=y BR2_ROOTFS_SKELETON_CUSTOM=y BR2_ROOTFS_SKELETON_CUSTOM_PATH="${BR2_EXTERNAL_NERVES_PATH}/board/nerves-common/skeleton" BR2_INIT_NONE=y @@ -27,14 +27,14 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_NERVES_PATH}/board/nerves-common/rootfs_overl BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_NERVES_PATH}/board/nerves-common/post-build.sh ${NERVES_DEFCONFIG_DIR}/post-build.sh" BR2_ROOTFS_POST_IMAGE_SCRIPT="${NERVES_DEFCONFIG_DIR}/post-createfs.sh" BR2_LINUX_KERNEL=y -BR2_LINUX_KERNEL_CUSTOM_TARBALL=y -BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="https://github.com/beagleboard/linux/archive/4.19.94-ti-r59.tar.gz" +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.15" BR2_LINUX_KERNEL_PATCH="${NERVES_DEFCONFIG_DIR}/linux" BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y -BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${NERVES_DEFCONFIG_DIR}/linux/linux-4.19.defconfig" +BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${NERVES_DEFCONFIG_DIR}/linux/linux-6.6.defconfig" BR2_LINUX_KERNEL_XZ=y BR2_LINUX_KERNEL_DTS_SUPPORT=y -BR2_LINUX_KERNEL_INTREE_DTS_NAME="am335x-boneblack am335x-bonegreen am335x-bonegreen-wireless am335x-boneblack-wireless am335x-pocketbeagle am335x-boneblack-uboot-univ am335x-bonegreen-wireless-uboot-univ am335x-bone-uboot-univ am335x-evmsk am335x-boneblue am335x-bonegreen-gateway" +BR2_LINUX_KERNEL_INTREE_DTS_NAME="ti/omap/am335x-boneblack ti/omap/am335x-bonegreen ti/omap/am335x-bonegreen-wireless ti/omap/am335x-boneblack-wireless ti/omap/am335x-pocketbeagle ti/omap/am335x-boneblack-uboot-univ ti/omap/am335x-bonegreen-wireless-uboot-univ ti/omap/am335x-evmsk ti/omap/am335x-boneblue ti/omap/am335x-bonegreen-gateway" BR2_LINUX_KERNEL_INSTALL_TARGET=y BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_NERVES_PATH}/board/nerves-common/busybox.config" @@ -45,6 +45,7 @@ BR2_PACKAGE_LINUX_FIRMWARE_RALINK_RT2XX=y BR2_PACKAGE_LINUX_FIRMWARE_RTL_87XX=y BR2_PACKAGE_LINUX_FIRMWARE_TI_WL18XX=y # BR2_PACKAGE_RNG_TOOLS_JITTERENTROPY_LIBRARY is not set +BR2_PACKAGE_CA_CERTIFICATES=y BR2_PACKAGE_LIBP11=y BR2_PACKAGE_UNIXODBC=y BR2_PACKAGE_BLUEZ_TOOLS=y diff --git a/package/extra-dts/extra-dts.mk b/package/extra-dts/extra-dts.mk index d136fdce..de88a11b 100644 --- a/package/extra-dts/extra-dts.mk +++ b/package/extra-dts/extra-dts.mk @@ -7,13 +7,13 @@ # Remember to bump the version when anything changes in this # directory. EXTRA_DTS_SOURCE = -EXTRA_DTS_VERSION = 0.0.1 +EXTRA_DTS_VERSION = 0.0.2 EXTRA_DTS_DEPENDENCIES = host-dtc define EXTRA_DTS_BUILD_CMDS cp $(NERVES_DEFCONFIG_DIR)/package/extra-dts/*.dts* $(@D) for filename in $(@D)/*.dts; do \ - $(CPP) -I$(@D) -nostdinc -undef -D__DTS__ -x assembler-with-cpp $$filename | \ + $(CPP) -I$(@D) -I $(LINUX_SRCDIR)include -I $(LINUX_SRCDIR)arch -nostdinc -undef -D__DTS__ -x assembler-with-cpp $$filename | \ $(HOST_DIR)/usr/bin/dtc -Wno-unit_address_vs_reg -@ -I dts -O dtb -b 0 -o $${filename%.dts}.dtbo || exit 1; \ done endef diff --git a/post-build.sh b/post-build.sh index 28d585a9..05969607 100755 --- a/post-build.sh +++ b/post-build.sh @@ -30,10 +30,12 @@ dd if=/dev/zero of=$TARGET_DIR/lib/firmware/ti-connectivity/wl127x-nvs.bin \ dd if=/dev/zero of=$TARGET_DIR/lib/firmware/ti-connectivity/wl127x-nvs.bin \ bs=1 count=2 seek=10 2> /dev/null -# Create the revert script for manually switching back to the previously -# active firmware. +# Create the fwup ops script to handling MicroSD/eMMC operations at runtime +# NOTE: revert.fw is the previous, more limited version of this. ops.fw is +# backwards compatible. mkdir -p $TARGET_DIR/usr/share/fwup -$HOST_DIR/usr/bin/fwup -c -f $NERVES_DEFCONFIG_DIR/fwup-revert.conf -o $TARGET_DIR/usr/share/fwup/revert.fw +$HOST_DIR/usr/bin/fwup -c -f $NERVES_DEFCONFIG_DIR/fwup-ops.conf -o $TARGET_DIR/usr/share/fwup/ops.fw +ln -sf ops.fw $TARGET_DIR/usr/share/fwup/revert.fw # Copy the fwup includes to the images dir cp -rf $NERVES_DEFCONFIG_DIR/fwup_include $BINARIES_DIR diff --git a/rootfs_overlay/etc/erlinit.config b/rootfs_overlay/etc/erlinit.config index 0aeba7e7..4a8b965c 100644 --- a/rootfs_overlay/etc/erlinit.config +++ b/rootfs_overlay/etc/erlinit.config @@ -48,7 +48,10 @@ #--run-on-exit /bin/sh # Enable UTF-8 filename handling in Erlang and custom inet configuration --e LANG=en_US.UTF-8;LANGUAGE=en;ERL_INETRC=/etc/erl_inetrc;ERL_CRASH_DUMP=/root/crash.dump +-e LANG=en_US.UTF-8;LANGUAGE=en;ERL_INETRC=/etc/erl_inetrc + +# Enable crash dumps (set ERL_CRASH_DUMP_SECONDS=0 to disable) +-e ERL_CRASH_DUMP=/root/erl_crash.dump;ERL_CRASH_DUMP_SECONDS=5 # Mount the application partition (run "man fstab" for field names) # NOTE: This must match the location in the fwup.conf. If it doesn't the system diff --git a/test/.gitignore b/test/.gitignore deleted file mode 100644 index d2e75565..00000000 --- a/test/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -# The directory Mix will write compiled artifacts to. -/_build/ - -# If you run "mix test --cover", coverage assets end up here. -/cover/ - -# The directory Mix downloads your dependencies sources to. -/deps/ - -# Where 3rd-party dependencies like ExDoc output generated docs. -/doc/ - -# Ignore .fetch files in case you like to edit your project deps locally. -/.fetch - -# If the VM crashes, it generates a dump, let's ignore it too. -erl_crash.dump -.env -.nerves_hub diff --git a/test/README.md b/test/README.md deleted file mode 100644 index 90f7cb61..00000000 --- a/test/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# C2 Test Suite - -Executes ExUnit tests on target hardware and reports results to the -[Nerves test server](https://nerves-test-server.herokuapp.com/nerves-project/nerves_system_bbb) - -For more information on how to configure your own test farm please refer to the -[Nerves test server source](https://github.com/mobileoverlord/nerves_test_server) - -## Setup - -### Signing firmware - -Firmware for the test farm is signed so it can be validated before being applied -to the device. In order to sign trusted firmware, you will require the env variable -`NERVES_FW_PRIV_KEY` and `NERVES_FW_PUB_KEY` to be set. Use `fwup` to configure -your own test server keys - -``` -$ fwup -g -``` - -The get the base64 values and export the variables -``` -$ export NERVES_FW_PRIV_KEY=$(cat fwup-key.priv | base64) -$ export NERVES_FW_PUB_KEY=$(cat fwup-key.pub | base64) -``` - -### Configure the environment - -``` -$ export MIX_ENV=test -$ export NERVES_TEST_SERVER=nerves-test-server.herokuapp.com -$ export WEBSOCKET_PROTOCOL=wss -``` - -### Building - -Fetch the dependencies - -``` -$ mix deps.get -``` - -Create the firmware - -``` -$ mix firmware -``` - -Sign the firmware - -``` -$ fwup --sign --private-key $NERVES_FW_PRIV_KEY -i _build/test/nerves/images/test.fw -o _build/test/nerves/images/test.fw -``` - -Burn it to an SD card - -``` -$ mix firmware.burn -``` - -## Provisioning - -The BeagleBone Black uses `eth0` to connect to the report server and requires a -wired ethernet connection. The device should establish a connection to the network and join the test farm. diff --git a/test/config/config.exs b/test/config/config.exs deleted file mode 100644 index 8320ed30..00000000 --- a/test/config/config.exs +++ /dev/null @@ -1,84 +0,0 @@ -import Config - -# Repository specific configuration - -platform = "c2" -arch = "arm" - -app_part_devparth = "/dev/mmcblk1p4" - -# Environment specific configuration -# Nerves Project test farm configuration -# NERVES_TEST_SERVER = nerves-test-server.herokuapp.com -# WEBSOCKET_PROTOCOL = wss - -test_server = System.get_env("NERVES_TEST_SERVER", "zola-nerves-test.herokuapp.com") -websocket_protocol = System.get_env("WEBSOCKET_PROTOCOL", "ws") - -Application.start(:nerves_bootstrap) -# Common configuration - -# Configure shoehorn boot order. -config :shoehorn, - app: :nerves_system_test, - init: [:nerves_runtime, :vintage_net] - -# Code.compile_file(Path.join(__DIR__, "nm_wifi.exs")) -import_config "nm_wifi.exs" -networks = Config.NmWifi.networks(System.get_env("WIFI_NETWORKS", "")) - -config :vintage_net, - regulatory_domain: System.get_env("NERVES_REGULATORY_DOMAIN", "us"), - config: [ - {"eth0", %{type: VintageNet.Technology.Ethernet, ipv4: %{method: :dhcp}}}, - {"wlan0", - %{ - type: VintageNetWiFi, - ipv4: %{method: :dhcp}, - vintage_net_wifi: %{networks: networks} - }} - ] - -config :nerves_ssh, - authorized_keys: [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCn4SWRN06jaYaI8j3Hn+GB5wHXkhxQjzlqLS/Vu7McYH9fenco6KBCiFFfBJ5jZuPOIYYB1Bcwg1GPljtC4tNTSJZIVJlujQx8dSA/g4u4Aslzjj7od7IXhAhZ6ks5qSiycmEWZZTB8HW60gcbXfOoWmbfVc07Aedc/bdj3talQBmK7UmSvPpUcKv+t2wv9R/IoBASbTTd/zjuUUBmqgMBYvLPa9DtEOTzuWM9ukBEBSQTrHYfJldgIkJRDkCRXFtVcJrO58EEtTdvGcl7rDnAXqnhHttiCpMdjjTdNzGJEIgOd5Mukh9FhWf0gWij8A0Jkv6E1osvrXz9ZPItYteB jgiffin", - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPbwMpJhNIVECuuggxX8zefr6Ufb56d+Zx2MPANNxRUh jean", - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf7zLrhnU++h/L8F4XhQoG9I1/0DCHe8iRMYXU9ThFpZ1Rm6D9OzrxfcjuMVCdbIGYox7XWkguALOgVOvXh+Fx3fP6+bTAmobUq/PwrnB7k0I9yf7flqKLyXh8/hkn2UmUDFxRSKVy0FkYq15UeaWotvrP0W+R2Vbw20y7wnaeKU9Zn7TPgSiSatDm49BxTChvhS522sj7Vvp+aYGMXKa609mBoSqDrv3ghU9auFLTOcv86Bsrz5bBwlrxKP6hDSXYl/x6fAg+LeOAuHXYpvXyx45flknZ1OT2SmhPcZCHBbjm+PhrKt+pfAJy0qrz2K66h0QU4BkhNc7nrFO6VN05 pi@raspberrypi" - ] - -# Configure the url for the connection to the test server phoenix channel socket. -config :nerves_test_client, url: "#{websocket_protocol}://#{test_server}/socket/websocket" - -# The configuration stored here is duplicated from the project so it can be -# validated by nerves_test_client because the source is unavailable at runtime. -config :nerves_runtime, :kv, - nerves_fw_application_part0_devpath: app_part_devparth, - nerves_fw_application_part0_fstype: "f2fs", - nerves_fw_application_part0_target: "/root", - nerves_fw_architecture: arch, - nerves_fw_author: "The Nerves Team", - nerves_fw_description: Mix.Project.config()[:description], - nerves_fw_platform: platform, - nerves_fw_product: Mix.Project.config()[:name], - nerves_fw_vcs_identifier: System.get_env("NERVES_FW_VCS_IDENTIFIER"), - nerves_fw_version: Mix.Project.config()[:version] - -nerves_hub_host = "nerves-hub-staging.zolaelectric.com" -nerves_hub_port = 443 - -# if Mix.target() != :host do -# config :nerves_hub_link, -# device_api_host: "device.#{nerves_hub_host}", -# device_api_sni: "device.#{nerves_hub_host}", -# device_api_port: nerves_hub_port, -# ca_store: NervesTestClient.CAStore, -# fwup_public_keys: [System.fetch_env!("FW_SIGNING_PUBKEY")] - -# config :nerves_hub_user_api, -# host: "api.#{nerves_hub_host}", -# port: nerves_hub_port, -# server_name_indication: 'api.#{nerves_hub_host}', -# ca_store: NervesTestClient.CAStore - -# config :nerves_hub_cli, org: "zola" -# end diff --git a/test/lib/test.ex b/test/lib/test.ex deleted file mode 100644 index 077fa74b..00000000 --- a/test/lib/test.ex +++ /dev/null @@ -1,83 +0,0 @@ -defmodule Test do - @moduledoc false - - def run(opts) do - opts - |> Keyword.put(:autorun, false) - |> ExUnit.configure() - - path = opts[:path] || runtime_include_path() - - case require_test_helper(path) do - :ok -> - tests = test_files([path]) - require_and_run(tests) - - error -> - error - end - end - - defp runtime_include_path() do - :code.root_dir() - |> to_string() - |> Path.join("test") - end - - defp require_test_helper(path) do - file = Path.join(path, "test_helper.exs") - - if File.exists?(file) do - Code.require_file(file) - :ok - else - {:error, "Cannot run tests because test helper file #{inspect(file)} does not exist"} - end - end - - defp test_files(paths) do - pattern = "*_test.exs" - - Enum.flat_map(paths, fn path -> - case :elixir_utils.read_file_type(path) do - {:ok, :directory} -> Path.wildcard("#{path}/**/#{pattern}") - {:ok, :regular} -> [path] - _ -> [] - end - end) - |> Enum.uniq() - end - - defp require_and_run(files) do - with {:ok, pid} <- Agent.start_link(fn -> [] end), - {:ok, _, _} <- - Kernel.ParallelCompiler.require(files, each_module: &each_module(pid, &1, &2, &3)) do - task = Task.async(ExUnit, :run, []) - - try do - {:ok, Task.await(task, :infinity)} - catch - _kind, reason -> - Task.shutdown(task) - {:error, reason} - after - Agent.get(pid, & &1) - |> unload_modules() - - Agent.stop(pid) - end - end - end - - def unload_modules(modules) do - Enum.each(modules, fn {mod, file} -> - :code.delete(mod) - :code.purge(mod) - Code.unrequire_files([file]) - end) - end - - defp each_module(pid, file, module, _binary) do - Agent.update(pid, &[{module, file} | &1]) - end -end diff --git a/test/mix.exs b/test/mix.exs deleted file mode 100644 index 7f8f71c4..00000000 --- a/test/mix.exs +++ /dev/null @@ -1,92 +0,0 @@ -if Mix.env() == :test do - hash = - :os.cmd('git rev-parse HEAD') - |> to_string - |> String.trim() - - System.put_env("NERVES_FW_VCS_IDENTIFIER", hash) -end - -defmodule Test.MixProject do - use Mix.Project - - @app :test - @targets [:target] - - def project do - [ - app: @app, - name: "system-test", - description: "System test", - version: "0.1.0", - elixir: "~> 1.9", - archives: [nerves_bootstrap: "~> 1.10"], - start_permanent: Mix.env() == :prod, - deps: deps(), - releases: [{@app, release()}], - aliases: aliases() - ] - end - - # Type `mix help compile.app` to learn about applications. - def application, do: [] - - # Run "mix help deps" to learn about dependencies. - defp deps do - [ - {:toolshed, "~> 0.2"}, - {:nerves_runtime, "~> 0.13"}, - {:zola_ca, git: "git@github.com:OffgridElectric/zola_ca.git"}, - {:nerves_system_c2, path: "../", runtime: false, targets: @targets}, - {:shoehorn, "~> 0.8"}, - {:nerves_test_client, git: "git@github.com:OffgridElectric/nerves_test_client.git"}, - {:nerves_key, "~> 1.1", targets: @targets}, - {:nerves_runtime_shell, "~> 0.1.0"}, - {:circuits_uart, "~> 1.5"} - ] - end - - def release do - [ - overwrite: true, - cookie: "#{@app}_cookie", - include_erts: &Nerves.Release.erts/0, - steps: [&Nerves.Release.init/1, :assemble, &ExUnitRelease.include/1] - ] - end - - defp aliases do - [ - remote_test: [&remote_test/1], - remote_devtest: [&remote_devtest/1] - ] - end - - defp remote_test(args) do - Mix.shell().cmd("ssh #{test_device_ip(args)} 'Test.run([])'") - end - - defp remote_devtest(args) do - path = "/tmp/test" - localdir = Path.absname(Path.join(__DIR__, "rel/test")) - - batch = """ - mkdir #{path} - cd #{path} - lcd #{localdir} - put -R * - exit - """ - - ip = test_device_ip(args) - - Mix.shell().cmd("ssh #{ip} 'File.rm_rf(\"#{path}\")'; echo \"#{batch}\" | sftp -b - #{ip}", quiet: true) - Mix.shell().cmd("ssh #{ip} 'Test.run(path: \"#{path}\")'") - end - - defp test_device_ip([ip]), do: ip - - defp test_device_ip([]) do - System.fetch_env!("TEST_DEVICE_IP") - end -end diff --git a/test/mix.lock b/test/mix.lock deleted file mode 100644 index f0ac5fd5..00000000 --- a/test/mix.lock +++ /dev/null @@ -1,82 +0,0 @@ -%{ - "atecc508a": {:hex, :atecc508a, "1.1.0", "8bcbc5e46e04cd48d5cf2c219559e65b4333fd85cbb86bc659f8993312014a69", [:mix], [{:circuits_i2c, "~> 1.0 or ~> 0.2", [hex: :circuits_i2c, repo: "hexpm", optional: false]}, {:x509, "~> 0.5.1 or ~> 0.6", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "ebfdacc6b40e8051ac550e7df45b8d5f1f78fdc39d771d2d8209e16ad02196ac"}, - "beam_notify": {:hex, :beam_notify, "1.0.0", "5b8dceed76f8ac4acadf4d2915ac85b98c42bb17d7dd58253c7593d2a0deedbd", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "a80331f6c3596918affa408d91ed634106b7ae71b3fc589432363aca68378362"}, - "castore": {:hex, :castore, "0.1.18", "deb5b9ab02400561b6f5708f3e7660fc35ca2d51bfc6a940d2f513f89c2975fc", [:mix], [], "hexpm", "61bbaf6452b782ef80b33cdb45701afbcf0a918a45ebe7e73f1130d661e66a06"}, - "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, - "circuits_i2c": {:hex, :circuits_i2c, "1.0.1", "3a820dfa04bc5a92d0ec3c572cacb1a665802b2913fbc25784ed5a2020f12626", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "e11393b3f462154ebec5d100859bd5d616e958d9f701e4d62af5764ee84f5213"}, - "circuits_uart": {:hex, :circuits_uart, "1.5.1", "c28f0144db799a8dbe84e1a05a58808450dd13a48b4e8ed92aa0a785ccfbbb1d", [:mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "e0690f814e39c0e7cc742ccd1421d5489f6a7627477ff64c1dbaf7520c1b5600"}, - "circular_buffer": {:hex, :circular_buffer, "0.4.1", "477f370fd8cfe1787b0a1bade6208bbd274b34f1610e41f1180ba756a7679839", [:mix], [], "hexpm", "633ef2e059dde0d7b89bbab13b1da9d04c6685e80e68fbdf41282d4fae746b72"}, - "connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"}, - "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, - "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, - "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, - "db_connection": {:hex, :db_connection, "2.4.2", "f92e79aff2375299a16bcb069a14ee8615c3414863a6fef93156aee8e86c2ff3", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4fe53ca91b99f55ea249693a0229356a08f4d1a7931d8ffa79289b145fe83668"}, - "decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"}, - "ecto": {:hex, :ecto, "3.9.2", "017db3bc786ff64271108522c01a5d3f6ba0aea5c84912cfb0dd73bf13684108", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "21466d5177e09e55289ac7eade579a642578242c7a3a9f91ad5c6583337a9d15"}, - "ecto_sql": {:hex, :ecto_sql, "3.9.1", "9bd5894eecc53d5b39d0c95180d4466aff00e10679e13a5cfa725f6f85c03c22", [:mix], [{:db_connection, "~> 2.5 or ~> 2.4.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5fd470a4fff2e829bbf9dcceb7f3f9f6d1e49b4241e802f614de6b8b67c51118"}, - "elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"}, - "ex_unit_release": {:git, "https://github.com/OffgridElectric/ex_unit_release.git", "9d34496a22a2853b3faa78ad5db9400b53456985", []}, - "extty": {:hex, :extty, "0.2.1", "4da6d78d41f0a9ff9980d82968476b4277ac0afa227d2ed91af0ffcbac2f451b", [:mix], [], "hexpm", "26b2e495c14501d4ae24c7dffba199f6abf0a0f69dcfd07db62f421952442f05"}, - "fwup": {:hex, :fwup, "1.1.0", "6c9d5f06a38263855dcf34f5a5b4da46c2ca42f6e3f873b8f932d095ce010765", [:mix], [], "hexpm", "3ff61d932a42785efc3324ecab6cf9bd3de75dacfca16d9e659a7173ef9f15d6"}, - "gen_state_machine": {:hex, :gen_state_machine, "3.0.0", "1e57f86a494e5c6b14137ebef26a7eb342b3b0070c7135f2d6768ed3f6b6cdff", [:mix], [], "hexpm", "0a59652574bebceb7309f6b749d2a41b45fdeda8dbb4da0791e355dd19f0ed15"}, - "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, - "hpax": {:hex, :hpax, "0.1.1", "2396c313683ada39e98c20a75a82911592b47e5c24391363343bde74f82396ca", [:mix], [], "hexpm", "0ae7d5a0b04a8a60caf7a39fcf3ec476f35cc2cc16c05abea730d3ce6ac6c826"}, - "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, - "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, - "mdns_lite": {:hex, :mdns_lite, "0.8.6", "cafdcde5be222d151342629637ec3178619090e4668a57c8cfdc67d970d0b268", [:mix], [{:vintage_net, "~> 0.7", [hex: :vintage_net, repo: "hexpm", optional: true]}], "hexpm", "7b6fcf2d45be8823492b77380f69510327d3a98f6b17d403f355daf31e1ac961"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, - "mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"}, - "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, - "mint": {:hex, :mint, "1.4.2", "50330223429a6e1260b2ca5415f69b0ab086141bc76dc2fbf34d7c389a6675b2", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "ce75a5bbcc59b4d7d8d70f8b2fc284b1751ffb35c7b6a6302b5192f8ab4ddd80"}, - "mint_web_socket": {:hex, :mint_web_socket, "1.0.0", "b33e534a938ec10736cef2b00cd485f6abd70aef68b9194f4d92fe2f7b8bba06", [:mix], [{:mint, "~> 1.4 and >= 1.4.1", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "3d4fd81190fe60f16fef5ade89e008463d72e6a608a7f6af9041cd8b47458e30"}, - "muontrap": {:hex, :muontrap, "1.0.0", "53a05c37f71cc5070aaa0858a774ae1f500160b7186a70565521a14ef7843c5a", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "0d3cd6e335986f9c2af1b61f583375b0f0d91cea95b7ec7bc720f330b4dc9b49"}, - "nerves": {:hex, :nerves, "1.8.0", "2735cda2037985411ede03c59937e9cb222f8990d5540e1a0e1ec77db96618cc", [:make, :mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "878c82ec079cf75ea48229ce802d2c2edf24bee60c17c33e477b18f83f7a49e1"}, - "nerves_hub_ca": {:git, "https://github.com/nerves-hub/nerves_hub_ca.git", "5d8c7bed3fc0b151b496592b3c1dc4422680699c", []}, - "nerves_hub_ca_store": {:hex, :nerves_hub_ca_store, "1.0.0", "d8681e8f08d2d1b8a43184a5e8370066f62b949a4bcf19cde880a0dbe45bb1f4", [:mix], [{:x509, "~> 0.5", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "01fbf3edc64be5bf8f3fc65f7f8ca6b82dab650af4373e201b6d441ded476c84"}, - "nerves_hub_cli": {:hex, :nerves_hub_cli, "0.12.0", "ea5b9ef0371b13494210dffc0dfdb6e6da181f9638350f6e6b7e6f7425657f06", [:mix], [{:nerves_hub_user_api, "~> 0.9.0", [hex: :nerves_hub_user_api, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 0.7 or ~> 1.1", [hex: :nimble_csv, repo: "hexpm", optional: false]}, {:pbcs, "== 0.1.2 or ~> 0.1.4", [hex: :pbcs, repo: "hexpm", optional: false]}, {:table_rex, "~> 2.0.0 or ~> 3.0", [hex: :table_rex, repo: "hexpm", optional: false]}, {:x509, "~> 0.3", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "98e1890437613e170df34b257ebf1ddb8f7efc502c4a0c2ce377bf3184fd2be7"}, - "nerves_hub_link": {:hex, :nerves_hub_link, "1.2.0", "01244172c030def7bace5ba104aaf75b5672d679a93af7d54761f5a1b89b8888", [:mix], [{:extty, "~> 0.2", [hex: :extty, repo: "hexpm", optional: false]}, {:fwup, "~> 1.0", [hex: :fwup, repo: "hexpm", optional: false]}, {:hackney, "~> 1.10", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:nerves_hub_ca_store, "~> 1.0.0", [hex: :nerves_hub_ca_store, repo: "hexpm", optional: false]}, {:nerves_hub_cli, "~> 0.11", [hex: :nerves_hub_cli, repo: "hexpm", optional: false]}, {:nerves_hub_link_common, "~> 0.4", [hex: :nerves_hub_link_common, repo: "hexpm", optional: false]}, {:nerves_key, "~> 1.0 or ~> 0.5", [hex: :nerves_key, repo: "hexpm", optional: true]}, {:nerves_runtime, "~> 0.8", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:slipstream, "~> 1.0 or ~> 0.8", [hex: :slipstream, repo: "hexpm", optional: false]}, {:x509, "~> 0.5", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "21274a6dfed262b66d849718e6e9283cbbde2173fb62fcee1fa380ec5304f9a9"}, - "nerves_hub_link_common": {:hex, :nerves_hub_link_common, "0.4.1", "efa35947e2c7145c4152300e0124e7fa9efc72179080dd3faaa4eb57a191669e", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:fwup, "~> 1.0", [hex: :fwup, repo: "hexpm", optional: false]}, {:mint, "~> 1.2", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "0aabbd63bd7e7ca035f0c812b58815a2b8571d5401ee51e3c2783934b3c666f9"}, - "nerves_hub_user_api": {:hex, :nerves_hub_user_api, "0.9.1", "5be21cdbab2a42060719f7da9d095c1353f6ada5d6c3a67ce8e0dc639db0d87a", [:mix], [{:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:nerves_hub_ca_store, "~> 1.0.0", [hex: :nerves_hub_ca_store, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2.1 or ~> 1.3", [hex: :tesla, repo: "hexpm", optional: false]}, {:x509, "~> 0.3", [hex: :x509, repo: "hexpm", optional: false]}], "hexpm", "6ad2c59ccfc3d1de9179b8c2618a356dc5eeecf01f610dbc4eb7a009fe2f3fa4"}, - "nerves_key": {:hex, :nerves_key, "1.1.0", "bb32a77e769e049607b546566bb676e51f9c71a393adce9d71d3b92280a64916", [:mix], [{:atecc508a, "~> 1.1 or ~> 0.3.0", [hex: :atecc508a, repo: "hexpm", optional: false]}, {:nerves_key_pkcs11, "~> 1.0 or ~> 0.2", [hex: :nerves_key_pkcs11, repo: "hexpm", optional: false]}], "hexpm", "ba19f49bf9f3d253f3e93d084bb17ffd825476a0517c585e08e6c46ee28cf270"}, - "nerves_key_pkcs11": {:hex, :nerves_key_pkcs11, "1.1.0", "b24edcbf079b311fe18bb411a7d3cc32a5dea4a70de20c8f3bde8b96a0db0044", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "c11b955aaf4da2d3225e9f7edc2203d8cc3a7da37763829a869a9296ee9583fb"}, - "nerves_logging": {:hex, :nerves_logging, "0.2.0", "4099b860f41a0171ff49fbc1e86ee0ce4576c24c1cf318a0fd0bf227355e8c12", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "07cfb9fe9d21b908da51b81a1ced858288c68519204aca7aa2c1fcd531d5e059"}, - "nerves_motd": {:hex, :nerves_motd, "0.1.7", "33d7818767a2065ad793e30d9508c8c7076e17746baf89778f637a0e47ca291b", [:mix], [{:nerves_runtime, "~> 0.8", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:nerves_time_zones, "~> 0.1", [hex: :nerves_time_zones, repo: "hexpm", optional: true]}], "hexpm", "8d631eb9407ca206d5d6d8e68dfba88aea635a25c150e5a00a2fa78791349bb7"}, - "nerves_pack": {:hex, :nerves_pack, "0.7.0", "bc93834edbb9321b180dc104440070279eb02159359715f68f770e74ed86a582", [:mix], [{:mdns_lite, "~> 0.8", [hex: :mdns_lite, repo: "hexpm", optional: false]}, {:nerves_motd, "~> 0.1", [hex: :nerves_motd, repo: "hexpm", optional: false]}, {:nerves_runtime, "~> 0.6", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:nerves_ssh, "~> 0.3", [hex: :nerves_ssh, repo: "hexpm", optional: false]}, {:nerves_time, "~> 0.3", [hex: :nerves_time, repo: "hexpm", optional: false]}, {:ring_logger, "~> 0.8", [hex: :ring_logger, repo: "hexpm", optional: false]}, {:vintage_net, "~> 0.10", [hex: :vintage_net, repo: "hexpm", optional: false]}, {:vintage_net_direct, "~> 0.10", [hex: :vintage_net_direct, repo: "hexpm", optional: false]}, {:vintage_net_ethernet, "~> 0.10", [hex: :vintage_net_ethernet, repo: "hexpm", optional: false]}, {:vintage_net_wifi, "~> 0.10", [hex: :vintage_net_wifi, repo: "hexpm", optional: false]}], "hexpm", "65a43ea78c10938c87c72d6d42a82c05e831e9a95a0ea26fe8f9d848c009cc57"}, - "nerves_runtime": {:hex, :nerves_runtime, "0.13.1", "b5f87675d8e07a4e5f29c2fe2f7d026467a84f604962dc0f4fb381f3928438f7", [:mix], [{:nerves_logging, "~> 0.2.0", [hex: :nerves_logging, repo: "hexpm", optional: false]}, {:nerves_uevent, "~> 0.1.0", [hex: :nerves_uevent, repo: "hexpm", optional: false]}, {:uboot_env, "~> 1.0 or ~> 0.3.0", [hex: :uboot_env, repo: "hexpm", optional: false]}], "hexpm", "bd7f41fb43d29bbfa32c164ac3cead3da04244a84108c2bcc70bbd130a5839ae"}, - "nerves_runtime_shell": {:hex, :nerves_runtime_shell, "0.1.0", "45330fa18c119c9874f4121c08bc6ac719802de5da40c003c107019ca556f95c", [:mix], [], "hexpm", "f59a5cada632d6e61f0ac67d8149a8b310258b53af90fd9a51d8e40b6b4e8bb0"}, - "nerves_ssh": {:hex, :nerves_ssh, "0.4.0", "cca3990bd8765c1fef0546065d45fb1f1fa39ca64125e7eba9a875553baa865f", [:mix], [{:nerves_runtime, "~> 0.11", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:ssh_subsystem_fwup, "~> 0.5", [hex: :ssh_subsystem_fwup, repo: "hexpm", optional: false]}], "hexpm", "34323780d9f355ac4336d077f8029aa7d7e42256f8e63048e35b806d3cbb1aad"}, - "nerves_system_br": {:hex, :nerves_system_br, "1.20.3", "8f3b69f9458b4b71ca2db0cd40c8894ea7705f15097e7111ad37f631edea4c16", [:mix], [], "hexpm", "c5a7b781455b3b982132299b0975ee3aade345cc51dc68a50e6b7bb556badbd5"}, - "nerves_test_client": {:git, "git@github.com:OffgridElectric/nerves_test_client.git", "ad60bd14dc8e1bed4835bb2b41c48ad45ed16b5f", []}, - "nerves_time": {:hex, :nerves_time, "0.4.5", "038d6754421b20f21eff8918f006d26a2c3e7440dc6954c4164030427e9228d8", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:muontrap, "~> 1.0 or ~> 0.5", [hex: :muontrap, repo: "hexpm", optional: false]}], "hexpm", "cbe4593bb63ba6fd66f09c321f558037ca9de6ad8b93bc0dc77c4209c4734a88"}, - "nerves_toolchain_armv7_nerves_linux_gnueabihf": {:hex, :nerves_toolchain_armv7_nerves_linux_gnueabihf, "1.6.0", "ed30bc7cb1853ef306a185cf2b24f9e8fb296dbc2839bf303302b46288c2cbd3", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.9.0", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm", "ed68e12550f9b5ed4eda1b291a3ef2368a99a3fd89690a207b8f9cd576861109"}, - "nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.9.0", "fe53615624763eeb5db6a5022a4fb5de8622405f314dba089b17fbf35d502529", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}], "hexpm", "80b0225108960a8433a81c0fbb5df1508b4015c222077361895e1b3a2f7c42d1"}, - "nerves_uevent": {:hex, :nerves_uevent, "0.1.0", "651111a46be9a238560cbf7946989fc500e5f33d7035fd9ea7194d07a281bc19", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:property_table, "~> 0.2.0", [hex: :property_table, repo: "hexpm", optional: false]}], "hexpm", "cb0b1993c3ed3cefadbcdb534e910af0661f95c3445796ce8a7c8be3519a4e5f"}, - "nimble_csv": {:hex, :nimble_csv, "1.2.0", "4e26385d260c61eba9d4412c71cea34421f296d5353f914afe3f2e71cce97722", [:mix], [], "hexpm", "d0628117fcc2148178b034044c55359b26966c6eaa8e2ce15777be3bbc91b12a"}, - "nimble_options": {:hex, :nimble_options, "0.4.0", "c89babbab52221a24b8d1ff9e7d838be70f0d871be823165c94dd3418eea728f", [:mix], [], "hexpm", "e6701c1af326a11eea9634a3b1c62b475339ace9456c1a23ec3bc9a847bca02d"}, - "one_dhcpd": {:hex, :one_dhcpd, "2.0.1", "d2d24dcb29f84072f3666580e4fb297ce8533c61667f78c94643ad37d586f7b8", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "1558faedeb560bb358827864bec3e862eadfcbaa589f9c2d457f49c833db704c"}, - "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, - "pbcs": {:hex, :pbcs, "0.1.4", "84c64d6ec826a57821021c03b0db3598ee587ba64430badee77809c2f68a9f8c", [:mix], [], "hexpm", "1f96954e50077e9cfde3cce62da452f4e56906d019ef141c011a96f79137dec0"}, - "plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"}, - "plug_cowboy": {:hex, :plug_cowboy, "2.6.0", "d1cf12ff96a1ca4f52207c5271a6c351a4733f413803488d75b70ccf44aebec2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "073cf20b753ce6682ed72905cd62a2d4bd9bad1bf9f7feb02a1b8e525bd94fa6"}, - "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"}, - "postgrex": {:hex, :postgrex, "0.16.5", "fcc4035cc90e23933c5d69a9cd686e329469446ef7abba2cf70f08e2c4b69810", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "edead639dc6e882618c01d8fc891214c481ab9a3788dfe38dd5e37fd1d5fb2e8"}, - "property_table": {:hex, :property_table, "0.2.0", "d47549d9c75c4f8975ca126b48a21c879c76e73d7e7dd0cc65b7d1619b3a198f", [:mix], [], "hexpm", "00f89af46c1f45e572c8386744c773fbf506f731648538d350b9a96720021f0d"}, - "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, - "ring_logger": {:hex, :ring_logger, "0.8.5", "e807c5b29993cb5e64afbcff41a5a7c44c44f3293ee17dd6601439b408f48903", [:mix], [{:circular_buffer, "~> 0.4.0", [hex: :circular_buffer, repo: "hexpm", optional: false]}], "hexpm", "1a29ec270ed9961b1b999a378bce5ea47d4ea9f3a3b8c53c67c05562b897e31b"}, - "shoehorn": {:hex, :shoehorn, "0.9.1", "8e12670024c2942e3c2fdd27cd5a034ee0337ee7c25c37b3ebc2ad482de67199", [:mix], [], "hexpm", "fccd040ac22de9b3cc111bbf78a363832c7210010a3fff4a550fbb2f10de0692"}, - "slipstream": {:hex, :slipstream, "1.0.1", "0b2f6990178a0f1eddec11a3318ca12c4ef3939f753565858256c7abd73266e5", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint_web_socket, "~> 1.0 or ~> 0.2", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.1", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0 or ~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3b7654de36654a9ff1a92becbe9081ae9689d5883ff304803b3193a3c0aba913"}, - "ssh_subsystem_fwup": {:hex, :ssh_subsystem_fwup, "0.6.1", "628f8e3795de5f1d0e7b3b55de4248ab0a77ab4c47e3cd282f1dda89d6354a9f", [:mix], [], "hexpm", "babdae337f2dc011ab5478662b4ec850650d7acfb165662ae47f6f0ce8892499"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, - "table_rex": {:hex, :table_rex, "3.1.1", "0c67164d1714b5e806d5067c1e96ff098ba7ae79413cc075973e17c38a587caa", [:mix], [], "hexpm", "678a23aba4d670419c23c17790f9dcd635a4a89022040df7d5d772cb21012490"}, - "telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"}, - "tesla": {:hex, :tesla, "1.4.4", "bb89aa0c9745190930366f6a2ac612cdf2d0e4d7fff449861baa7875afd797b2", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "d5503a49f9dec1b287567ea8712d085947e247cb11b06bc54adb05bfde466457"}, - "toolshed": {:hex, :toolshed, "0.2.26", "1e50c8ff6da61d304dd59598667c403ff0873319afb73f40efda775a49e00c93", [:mix], [{:nerves_runtime, "~> 0.8", [hex: :nerves_runtime, repo: "hexpm", optional: true]}], "hexpm", "7e92e03731ed39c1261d5baf58576a771d116e2e3461db35cdd45c78a6b999b2"}, - "uboot_env": {:hex, :uboot_env, "1.0.0", "fdbe0afe65436f760cd372b16a58ccf7c76bbad1538f1766826e0ddbcaf80980", [:mix], [], "hexpm", "86754d5eae9643ca3094ee1d749b808f9d6f0d41b990e1191709b5a66c2b0757"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, - "vintage_net": {:hex, :vintage_net, "0.12.2", "2e6b858f0f4000476758a20ac72aefff899ec25adeb0233f284547b59f287dc4", [:make, :mix], [{:beam_notify, "~> 1.0 or ~> 0.2.0", [hex: :beam_notify, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:gen_state_machine, "~> 2.0.0 or ~> 2.1.0 or ~> 3.0.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:muontrap, "~> 1.0 or ~> 0.5.1 or ~> 0.6.0", [hex: :muontrap, repo: "hexpm", optional: false]}, {:property_table, "~> 0.2.0", [hex: :property_table, repo: "hexpm", optional: false]}], "hexpm", "8a3a55a5797d89daae591ede297e99883b29ce3e148d605f0e61fbb58203569b"}, - "vintage_net_direct": {:hex, :vintage_net_direct, "0.10.6", "a5e9ba836a6e384a3beebb65b3ed9d977d3487e1bd8889851bfe301b3a300393", [:mix], [{:one_dhcpd, "~> 2.0 or ~> 1.0 or ~> 0.2.3", [hex: :one_dhcpd, repo: "hexpm", optional: false]}, {:vintage_net, "~> 0.9.1 or ~> 0.10.0 or ~> 0.11.0 or ~> 0.12.0", [hex: :vintage_net, repo: "hexpm", optional: false]}], "hexpm", "f3927a0c1aea864eb70beb6267c7f2fa404985305ad3919cca737038920c9d35"}, - "vintage_net_ethernet": {:hex, :vintage_net_ethernet, "0.11.0", "3610e7961f0b595043b196e80e0eed86acf38098b65bfcb7fad1d30911bd2313", [:mix], [{:vintage_net, "~> 0.12.0", [hex: :vintage_net, repo: "hexpm", optional: false]}], "hexpm", "7720c70dee5955610a82ef9c4f6a57ae93f0fb717f29547c6a709a1baec8ac23"}, - "vintage_net_wifi": {:hex, :vintage_net_wifi, "0.11.1", "efbcc0eff75acfd0982044028dd6c8a73fc89a06fea9db6d64f10ae7dff8441c", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:vintage_net, "~> 0.12.0", [hex: :vintage_net, repo: "hexpm", optional: false]}], "hexpm", "7a40fd6d8a23eda1b866e14a2c5442f9a02ad5c02a2ee4f5ce08d86c7ce2632b"}, - "x509": {:hex, :x509, "0.8.5", "22b2c5dfc87b05d46595d3764f41a23fcb7360f891e0464f1a2ec118177cd4e4", [:mix], [], "hexpm", "c63eb89e8bbe8a5e21b6404ad1082faff670e38b74960297f90d023177949e07"}, - "zola_ca": {:git, "git@github.com:OffgridElectric/zola_ca.git", "e6e4381e0fb279fa643713a6fff37a767bb38474", []}, -} diff --git a/test/rel/test/nerves_runtime_test.exs b/test/rel/test/nerves_runtime_test.exs deleted file mode 100644 index 2a061c92..00000000 --- a/test/rel/test/nerves_runtime_test.exs +++ /dev/null @@ -1,37 +0,0 @@ -defmodule NervesRuntime.Test do - use ExUnit.Case - - describe "application data partition" do - test "can be written to" do - file = "/root/tmp" - content = "hello" - assert :ok == File.write(file, content) - assert {:ok, content} == File.read(file) - end - end - - describe "key value store" do - test "can be read from" do - tests = Application.get_env(:nerves_runtime, :kv) - - assert Enum.all?(tests, fn {k, v} -> - v = - to_string(v) - |> String.trim() - - kv = - to_string(k) - |> Nerves.Runtime.KV.get_active() - |> String.trim() - - v == kv - end) - end - end - - test "hostname has the form nerves-id" do - {:ok, hostname} = :inet.gethostname() - hostname = to_string(hostname) - assert String.match?(hostname, ~r/^nerves-[[:alnum:]]+$/) - end -end diff --git a/test/rel/test/test_helper.exs b/test/rel/test/test_helper.exs deleted file mode 100644 index 869559e7..00000000 --- a/test/rel/test/test_helper.exs +++ /dev/null @@ -1 +0,0 @@ -ExUnit.start() diff --git a/test/rel/test/test_test.exs b/test/rel/test/test_test.exs deleted file mode 100644 index 5bda5929..00000000 --- a/test/rel/test/test_test.exs +++ /dev/null @@ -1,8 +0,0 @@ -defmodule TestTest do - use ExUnit.Case - - test "i2c interface exists" do - assert File.exists?("/dev/i2c-0") - assert File.exists?("/dev/i2c-1") - end -end diff --git a/test/rel/vm.args.eex b/test/rel/vm.args.eex deleted file mode 100644 index 6eec484a..00000000 --- a/test/rel/vm.args.eex +++ /dev/null @@ -1,43 +0,0 @@ -## Add custom options here - -## Distributed Erlang Options -## The cookie needs to be configured prior to vm boot for -## for read only filesystem. - --setcookie <%= @release.options[:cookie] %> - -## Use Ctrl-C to interrupt the current shell rather than invoking the emulator's -## break handler and possibly exiting the VM. -+Bc - -# Allow time warps so that the Erlang system time can more closely match the -# OS system time. -+C multi_time_warp - -## Load code at system startup -## See http://erlang.org/doc/system_principles/system_principles.html#code-loading-strategy --mode embedded - -## Save the shell history between reboots -## See http://erlang.org/doc/man/kernel_app.html for additional options --kernel shell_history enabled - -## Enable heartbeat monitoring of the Erlang runtime system --heart -env HEART_BEAT_TIMEOUT 30 - -## Start the Elixir shell - --noshell --user Elixir.IEx.CLI - -## Enable colors in the shell --elixir ansi_enabled true - -## Options added after -extra are interpreted as plain arguments and can be -## retrieved using :init.get_plain_arguments(). Options before the "--" are -## interpreted by Elixir and anything afterwards is left around for other IEx -## and user applications. --extra --no-halt -#-- -#--dot-iex /etc/iex.exs -