From 38f2d26f1b6ed2847af2592de30d04cd0a6ace19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Tue, 6 Aug 2024 09:21:42 +0200 Subject: [PATCH 01/12] utils: omnia-mcutool: Bump to 0.3-rc3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump omnia-mcutool to 0.3-rc3: * The `--upgrade` option will now work even if MCU is in bootloader (for example if previous upgrade was aborted). * On boards with GD32 MCUs, `omnia-mcutool` will now refuse to upgrade application firmware to version lower than 4.1 if bootloader version is 2.0 (the original for first batch of boards with GD32 MCUs) since these versions of application and bootloader are not compatible. If user already upgraded to such a combination, an upgrade of bootloader firmware is required. The `--upgrade` option will inform about this and will automatically upgrade bootloader firmware if the `--force` option is given. (Note that version 4.1 of the MCU firmware was will be released soon, once it is properly tested.) * Various other improvements. Signed-off-by: Marek Behún Link: https://github.com/openwrt/openwrt/pull/16086 Signed-off-by: Robert Marko --- package/utils/omnia-mcutool/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/utils/omnia-mcutool/Makefile b/package/utils/omnia-mcutool/Makefile index d34ad014ae..493649b961 100644 --- a/package/utils/omnia-mcutool/Makefile +++ b/package/utils/omnia-mcutool/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=omnia-mcutool -PKG_VERSION:=0.3-rc2 +PKG_VERSION:=0.3-rc3 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://gitlab.nic.cz/turris/$(PKG_NAME)/-/archive/$(PKG_VERSION)/ -PKG_HASH:=68e407fca16ccaf4bd87401f710d6a4061029b4d474ac10c4c3253af73c242ac +PKG_HASH:=80bc6a01ab86d51ebfdbddf77d74eead999a9bf7dbd08ca1fd4e8e1910eaf192 PKG_MAINTAINER:=Marek Mojik PKG_LICENSE:=GPL-2.0-or-later From ce6145b8189f6eaae7b6ebd6c9770b56fb72b368 Mon Sep 17 00:00:00 2001 From: Mieczyslaw Nalewaj Date: Tue, 6 Aug 2024 07:36:10 +0200 Subject: [PATCH 02/12] kernel: Add kmod-mfd-test for kernel 6.6 only Compilation of mtd_test.ko should be added only for kernel 6.6 or above. Fixes 26df88a ("kernel: Add kmod-mfd-test") Signed-off-by: Mieczyslaw Nalewaj Link: https://github.com/openwrt/openwrt/pull/16085 Signed-off-by: Robert Marko --- package/kernel/linux/modules/other.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/linux/modules/other.mk b/package/kernel/linux/modules/other.mk index 222f8880bd..10cb61e8b1 100644 --- a/package/kernel/linux/modules/other.mk +++ b/package/kernel/linux/modules/other.mk @@ -597,7 +597,7 @@ define KernelPackage/mtdtests $(LINUX_DIR)/drivers/mtd/tests/mtd_speedtest.ko \ $(LINUX_DIR)/drivers/mtd/tests/mtd_stresstest.ko \ $(LINUX_DIR)/drivers/mtd/tests/mtd_subpagetest.ko \ - $(LINUX_DIR)/drivers/mtd/tests/mtd_test.ko \ + $(LINUX_DIR)/drivers/mtd/tests/mtd_test.ko@ge6.6 \ $(LINUX_DIR)/drivers/mtd/tests/mtd_torturetest.ko endef From c11adb4b53cb1573bd7700b80b0c18e05c33fba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 6 Aug 2024 12:33:48 +0200 Subject: [PATCH 03/12] generic: 6.6: add backported bmips CBR patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move v6.11 backported bmips CBR patches from bmips target to generic. Signed-off-by: Álvaro Fernández Rojas --- .../bcm47xx/patches-6.6/830-huawei_e970_support.patch | 8 ++++---- ...1-mips-bmips-rework-and-cache-CBR-addr-handling.patch} | 0 ...-mips-bmips-setup-make-CBR-address-configurable.patch} | 0 .../322-v6.11-mips-bmips-enable-RAC-on-BMIPS4350.patch} | 0 4 files changed, 4 insertions(+), 4 deletions(-) rename target/linux/{bmips/patches-6.6/020-v6.11-mips-bmips-rework-and-cache-CBR-addr-handling.patch => generic/backport-6.6/320-v6.11-mips-bmips-rework-and-cache-CBR-addr-handling.patch} (100%) rename target/linux/{bmips/patches-6.6/021-v6.11-mips-bmips-setup-make-CBR-address-configurable.patch => generic/backport-6.6/321-v6.11-mips-bmips-setup-make-CBR-address-configurable.patch} (100%) rename target/linux/{bmips/patches-6.6/022-v6.11-mips-bmips-enable-RAC-on-BMIPS4350.patch => generic/backport-6.6/322-v6.11-mips-bmips-enable-RAC-on-BMIPS4350.patch} (100%) diff --git a/target/linux/bcm47xx/patches-6.6/830-huawei_e970_support.patch b/target/linux/bcm47xx/patches-6.6/830-huawei_e970_support.patch index 21ab40206f..08813da1ba 100644 --- a/target/linux/bcm47xx/patches-6.6/830-huawei_e970_support.patch +++ b/target/linux/bcm47xx/patches-6.6/830-huawei_e970_support.patch @@ -1,14 +1,14 @@ --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c -@@ -37,6 +37,7 @@ - #include +@@ -38,6 +38,7 @@ #include #include + #include +#include #include #include #include -@@ -254,6 +255,33 @@ static struct fixed_phy_status bcm47xx_f +@@ -262,6 +263,33 @@ static struct fixed_phy_status bcm47xx_f .duplex = DUPLEX_FULL, }; @@ -42,7 +42,7 @@ static int __init bcm47xx_register_bus_complete(void) { switch (bcm47xx_bus_type) { -@@ -275,6 +303,7 @@ static int __init bcm47xx_register_bus_c +@@ -283,6 +311,7 @@ static int __init bcm47xx_register_bus_c bcm47xx_workarounds(); fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status); diff --git a/target/linux/bmips/patches-6.6/020-v6.11-mips-bmips-rework-and-cache-CBR-addr-handling.patch b/target/linux/generic/backport-6.6/320-v6.11-mips-bmips-rework-and-cache-CBR-addr-handling.patch similarity index 100% rename from target/linux/bmips/patches-6.6/020-v6.11-mips-bmips-rework-and-cache-CBR-addr-handling.patch rename to target/linux/generic/backport-6.6/320-v6.11-mips-bmips-rework-and-cache-CBR-addr-handling.patch diff --git a/target/linux/bmips/patches-6.6/021-v6.11-mips-bmips-setup-make-CBR-address-configurable.patch b/target/linux/generic/backport-6.6/321-v6.11-mips-bmips-setup-make-CBR-address-configurable.patch similarity index 100% rename from target/linux/bmips/patches-6.6/021-v6.11-mips-bmips-setup-make-CBR-address-configurable.patch rename to target/linux/generic/backport-6.6/321-v6.11-mips-bmips-setup-make-CBR-address-configurable.patch diff --git a/target/linux/bmips/patches-6.6/022-v6.11-mips-bmips-enable-RAC-on-BMIPS4350.patch b/target/linux/generic/backport-6.6/322-v6.11-mips-bmips-enable-RAC-on-BMIPS4350.patch similarity index 100% rename from target/linux/bmips/patches-6.6/022-v6.11-mips-bmips-enable-RAC-on-BMIPS4350.patch rename to target/linux/generic/backport-6.6/322-v6.11-mips-bmips-enable-RAC-on-BMIPS4350.patch From aeb9028aabf6bf90638a822d563f54a2c4146e6d Mon Sep 17 00:00:00 2001 From: Stan Grishin Date: Mon, 22 Jul 2024 08:05:51 +0000 Subject: [PATCH 04/12] base-files: improve Dell EMC Edge620 (x86) product support This adds auto-configuration of network ports on Dell EMC Edge620 (x86) product. It is similar in specs/features to some of the Sophos x86-based appliances, but: 1. Serial console terminal is built in and requires just the micro-USB cable 2. Comes with both MMC (16Gb) and SSD (256Gb) installed 3. Comes with 6 ethernet ports all 6 are functional when no SFP is used 4. Comes with two SFP cages and not one, like some of revision 3 Sophos products 5. Unlike Sophos devices, there are no non-wireless models of Edge 620, it comes with Qualcomm Atheros QCA9880 radio These devices can be now found both second-hand and new at online marketplaces below (sometimes well below) US $100, I believe they make great candidates for running OpenWrt. The ethernet network ports on the case are marked GE1 thru to GE6 with the following mapping once booted into OpenWrt: ``` GE1: eth2: pci0000:00/0000:00:0b.0/0000:02:00.2 GE2: eth3: pci0000:00/0000:00:0b.0/0000:02:00.3 GE3: eth0: pci0000:00/0000:00:0b.0/0000:02:00.0 GE4: eth1: pci0000:00/0000:00:0b.0/0000:02:00.1 GE5: eth7: pci0000:00/0000:00:17.0/0000:07:00.1 GE6: eth6: pci0000:00/0000:00:17.0/0000:07:00.0 ``` Dell's instructions for [standard configuration](https://infohub.delltechnologies.com/en-us/l/dell-emc-edge-620-advanced-activation-guide/dell-emc-sd-wan-edge-620-standard-configuration/) recommend using GE3, GE4, GE5, or GE6 for WAN, I've selected the GE6 as the sole WAN port under OpenWrt with the rest of ethernet ports assigned to LAN. Please merge before 24.xx is forked and if possible, cherry-pick for 23.05 if there's no ETA for 24.xx forking. PS. @Hurricos I'm struggling with ixgbe mappings on Sophos devices which use very similar hardware to Dell EMC, so even tho I know the sys paths for ethernet ports, I'd prefer to do a separate commit to properly map ethernet ports to match the case markings for this device at some point later. Signed-off-by: Stan Grishin --- target/linux/x86/base-files/etc/board.d/02_network | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/linux/x86/base-files/etc/board.d/02_network b/target/linux/x86/base-files/etc/board.d/02_network index 5174906264..c4c2d3fa21 100644 --- a/target/linux/x86/base-files/etc/board.d/02_network +++ b/target/linux/x86/base-files/etc/board.d/02_network @@ -31,6 +31,9 @@ cisco-mx100-hw) ucidef_set_network_device_path "eth11" "pci0000:00/0000:00:01.1/0000:02:00.2" ucidef_set_interfaces_lan_wan "mgmt eth2 eth3 eth4 eth5 eth6 eth7 eth8 eth9 eth10 eth11" "wan" ;; +dell-emc-edge620) + ucidef_set_interfaces_lan_wan "eth0 eth1 eth2 eth3 eth7" "eth6" + ;; pc-engines-apu1|pc-engines-apu2|pc-engines-apu3) ucidef_set_interfaces_lan_wan "eth1 eth2" "eth0" ;; From ef8c1adb61186d6059c960fea4e362f7cd26fd23 Mon Sep 17 00:00:00 2001 From: Paul Spooren Date: Tue, 6 Aug 2024 14:22:00 +0200 Subject: [PATCH 05/12] apk: switch to index-trust branch Initially APK would sign packages and package index and verify signatures individually. With the latest change, all packages inside a trusted index are automatically trusted. This is important within the OpenWrt eco-system since signing the index happens on another machine than the package creation. Signed-off-by: Paul Spooren --- package/system/apk/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/system/apk/Makefile b/package/system/apk/Makefile index a372e7cc9c..b8fdc05104 100644 --- a/package/system/apk/Makefile +++ b/package/system/apk/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_URL=https://gitlab.alpinelinux.org/alpine/apk-tools.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2024-05-23 -PKG_SOURCE_VERSION:=6052bfef57a81d82451b4cad86f78a2d01959767 -PKG_MIRROR_HASH:=bf14da82cc363ee32a956dd880343018361079018a48701dc2b05cb88c18010e +PKG_SOURCE_DATE:=2024-08-06 +PKG_SOURCE_VERSION:=54caa31be633efc5f655700b77af290124f71689 +PKG_MIRROR_HASH:=f3be762deac4f1469a4a2839691175e78019cb44295089befafa279a3390067c PKG_VERSION=3.0.0_pre$(subst -,,$(PKG_SOURCE_DATE)) From 0171157d45f1c8c068608b69afdcdef101e5a594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Wed, 3 Jul 2024 20:30:59 +0200 Subject: [PATCH 06/12] bcm27xx: update to latest RPi patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The patches were generated from the RPi repo with the following command: git format-patch v6.6.44..rpi-6.6.y Signed-off-by: Álvaro Fernández Rojas --- target/linux/bcm27xx/config-6.6 | 1 + ...t-the-last-DMA-scoop-out-of-the-FIFO.patch | 41 - ...use-C11-style-variable-array-declara.patch | 260 + ...fmt-luma-Document-MIPI-CSI-2-packing.patch | 27 + ...d-a-pixel-format-for-BGR48-and-RGB48.patch | 101 + ...-Add-Raspberry-Pi-PiSP-Back-End-uAPI.patch | 1171 ++ ...ent-meta-pixel-format-for-PiSP-BE-co.patch | 86 + ...ent-PiSP-Compressed-RAW-Bayer-format.patch | 106 + ...s-Add-bindings-for-Raspberry-Pi-PiSP.patch | 97 + ...de-Document-the-Raspberry-Pi-PiSP-BE.patch | 162 + ...Backport-the-mainline-PiSP-BE-driver.patch | 2927 +++++ ...pi-pisp_be_config-Drop-BIT-from-uAPI.patch | 29 + ...i-pisp_common-Add-32-bpp-format-test.patch | 32 + ...157-media-uapi-Capitalize-all-macros.patch | 89 + ...be_config-Re-sort-pisp_be_tiles_conf.patch | 30 + ...sp_be_config-Add-extra-config-fields.patch | 82 + ...e-Re-introduce-multi-context-support.patch | 886 ++ ...sp_be-Re-introduce-video-node-offset.patch | 36 + ...g-and-camN_reg_gpio-overrides-generi.patch | 158 + ...-bindings-Add-RPI-RP2040-GPIO-Bridge.patch | 108 + ...river-for-the-RPI-RP2040-GPIO-bridge.patch | 1288 +++ ...e-dw-axi-dmac-Honour-snps-block-size.patch | 52 + ...ted-write-counts-for-SD-cards-in-CQ-.patch | 157 + ...ct-posted-write-counts-for-SD-cards-.patch | 70 + ...t-squash-card-busy-detection-on-bcm2.patch | 28 + ...-Update-DAC8x-to-support-384khz-6187.patch | 25 + ...rp1-Add-clocks-representing-MIPI-DSI.patch | 25 + ...varsrc-clocks-to-represent-MIPI-byte.patch | 132 + ...ers-to-use-newly-defined-MIPI-byte-s.patch | 92 + ...Switch-to-PLL_SYS-source-for-DPI-whe.patch | 313 + ...-arm64-dts-Move-bcm2712-and-rp1-here.patch | 9749 +++++++++++++++++ .../950-1181-arm64-dts-Add-cm5l-files.patch | 92 + ...2712-Dedup-the-aliases-and-overrides.patch | 408 + ...m64-dts-Give-cm5l-its-own-model-name.patch | 24 + ...-through-hoops-to-avoid-PCIe-latency.patch | 288 + ...codec-Disable-HEADER_ON_OPEN-for-vid.patch | 36 + ...codec-Add-support-for-H264-level-5.0.patch | 36 + ...e-bandwidth-with-the-TMOD_TO-feature.patch | 66 + ...e-bandwidth-with-the-TMOD_RO-feature.patch | 186 + ...ediately-kill-DMA-transfers-if-an-er.patch | 41 + ...dts-rp1-hobble-DMA-AXI-burst-lengths.patch | 35 + ...mac-make-more-sensible-choices-about.patch | 124 + ...011-restrict-RX-burst-FIFO-threshold.patch | 30 + ...a-dma-maxburst-property-to-snps-desi.patch | 27 + ...s-choose-FIFO-thresholds-based-on-DM.patch | 99 + ...-rp1-restrict-i2s-burst-lengths-to-4.patch | 30 + ...the-2pixel-clock-odd-timings-workaro.patch | 204 + ...Fix-invalid-polling-delay-passive-se.patch | 26 + ...-Fix-non-DMA-transmit-only-transfers.patch | 143 + ...spi-dw-Clamp-the-minimum-clock-speed.patch | 26 + ...2c-rtc-Correct-bq32000-property-name.patch | 26 + ...on-adt7410-Add-DT-compatible-strings.patch | 31 + ...nctrl-bcm2712-pinctrl-pinconf-driver.patch | 23 + ...verlay-for-HD44780-via-I2C-PCF8574-b.patch | 125 + ...ent-display_-width-height-on-hd44780.patch | 28 + ...nable-SD-slot-CQE-by-default-on-Pi-5.patch | 39 + ...ide-gpiochip-numbers-with-DT-aliases.patch | 50 + ...-dts-bcm2712-rpi-Add-gpiochip0-alias.patch | 23 + ...12-rpi-The-SoC-gpiochips-start-at-10.patch | 24 + 59 files changed, 20609 insertions(+), 41 deletions(-) delete mode 100644 target/linux/bcm27xx/patches-6.6/950-0714-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1146-drivers-dwc_otg-use-C11-style-variable-array-declara.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1147-media-uapi-pixfmt-luma-Document-MIPI-CSI-2-packing.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1148-media-uapi-Add-a-pixel-format-for-BGR48-and-RGB48.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1149-media-uapi-Add-Raspberry-Pi-PiSP-Back-End-uAPI.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1150-media-uapi-Document-meta-pixel-format-for-PiSP-BE-co.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1151-media-uapi-Document-PiSP-Compressed-RAW-Bayer-format.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1152-media-dt-bindings-Add-bindings-for-Raspberry-Pi-PiSP.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1153-media-admin-guide-Document-the-Raspberry-Pi-PiSP-BE.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1154-media-pisp-be-Backport-the-mainline-PiSP-BE-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1155-media-uapi-pisp_be_config-Drop-BIT-from-uAPI.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1156-media-uapi-pisp_common-Add-32-bpp-format-test.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1157-media-uapi-Capitalize-all-macros.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1158-media-uapi-pisp_be_config-Re-sort-pisp_be_tiles_conf.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1159-media-uapi-pisp_be_config-Add-extra-config-fields.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1160-media-pisp_be-Re-introduce-multi-context-support.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1161-media-pisp_be-Re-introduce-video-node-offset.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1163-dts-Make-camN_reg-and-camN_reg_gpio-overrides-generi.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1164-spi-dt-bindings-Add-RPI-RP2040-GPIO-Bridge.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1165-spi-Add-a-driver-for-the-RPI-RP2040-GPIO-bridge.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1166-dmaengine-dw-axi-dmac-Honour-snps-block-size.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1167-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1168-fixup-mmc-restrict-posted-write-counts-for-SD-cards-.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1169-mmc-brcmstb-don-t-squash-card-busy-detection-on-bcm2.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1172-Revert-Update-DAC8x-to-support-384khz-6187.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1176-dt-bindings-clk-rp1-Add-clocks-representing-MIPI-DSI.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1177-clk-clk-rp1-Add-varsrc-clocks-to-represent-MIPI-byte.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1178-dts-rp1-DSI-drivers-to-use-newly-defined-MIPI-byte-s.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1179-drm-rp1-rp1-dsi-Switch-to-PLL_SYS-source-for-DPI-whe.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1180-arm64-dts-Move-bcm2712-and-rp1-here.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1181-arm64-dts-Add-cm5l-files.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1182-dts-bcm2712-Dedup-the-aliases-and-overrides.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1183-arm64-dts-Give-cm5l-its-own-model-name.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1185-pinctrl-rp1-jump-through-hoops-to-avoid-PCIe-latency.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1186-staging-bcm2835-codec-Disable-HEADER_ON_OPEN-for-vid.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1188-staging-bcm2835-codec-Add-support-for-H264-level-5.0.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1189-spi-dw-Save-bandwidth-with-the-TMOD_TO-feature.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1190-spi-dw-Save-bandwidth-with-the-TMOD_RO-feature.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1191-spi-dw-don-t-immediately-kill-DMA-transfers-if-an-er.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1192-dts-rp1-hobble-DMA-AXI-burst-lengths.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1193-drivers-dw-axi-dmac-make-more-sensible-choices-about.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1195-tty-serial-pl011-restrict-RX-burst-FIFO-threshold.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1196-DT-bindings-add-a-dma-maxburst-property-to-snps-desi.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1197-sound-soc-dwc-i2s-choose-FIFO-thresholds-based-on-DM.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1198-dts-rp1-restrict-i2s-burst-lengths-to-4.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1199-drm-vc4-Disable-the-2pixel-clock-odd-timings-workaro.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1200-ARM-dts-bcm2712-Fix-invalid-polling-delay-passive-se.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1201-spi-dw-Fix-non-DMA-transmit-only-transfers.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1202-spi-dw-Clamp-the-minimum-clock-speed.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1203-overlays-i2c-rtc-Correct-bq32000-property-name.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1204-hwmon-adt7410-Add-DT-compatible-strings.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1205-fixup-pinctrl-bcm2712-pinctrl-pinconf-driver.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1206-dtoverlays-Add-overlay-for-HD44780-via-I2C-PCF8574-b.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1207-dtoverlays-Document-display_-width-height-on-hd44780.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1208-DTS-bcm2712-enable-SD-slot-CQE-by-default-on-Pi-5.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1211-gpiolib-Override-gpiochip-numbers-with-DT-aliases.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1212-dts-bcm2712-rpi-Add-gpiochip0-alias.patch create mode 100644 target/linux/bcm27xx/patches-6.6/950-1213-dts-bcm2712-rpi-The-SoC-gpiochips-start-at-10.patch diff --git a/target/linux/bcm27xx/config-6.6 b/target/linux/bcm27xx/config-6.6 index 55f5523ab5..b44aa9f8a9 100644 --- a/target/linux/bcm27xx/config-6.6 +++ b/target/linux/bcm27xx/config-6.6 @@ -23,6 +23,7 @@ # CONFIG_RASPBERRYPI_GPIOMEM is not set # CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2 is not set # CONFIG_SENSORS_RP1_ADC is not set +# CONFIG_SPI_RP2040_GPIO_BRIDGE is not set # CONFIG_VIDEO_AD5398 is not set # CONFIG_VIDEO_ARDUCAM_64MP is not set # CONFIG_VIDEO_ARDUCAM_PIVARIETY is not set diff --git a/target/linux/bcm27xx/patches-6.6/950-0714-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch b/target/linux/bcm27xx/patches-6.6/950-0714-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch deleted file mode 100644 index 2a2ba5d037..0000000000 --- a/target/linux/bcm27xx/patches-6.6/950-0714-spi-dw-dma-Get-the-last-DMA-scoop-out-of-the-FIFO.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 6aab06ff9f81e186b1a02b53b514e691472e5a61 Mon Sep 17 00:00:00 2001 -From: Phil Elwell -Date: Tue, 7 Nov 2023 14:49:47 +0000 -Subject: [PATCH 0714/1085] spi: dw-dma: Get the last DMA scoop out of the FIFO - -With a DMA FIFO threshold greater than 1 (encoded as 0), it is possible -for data in the FIFO to be inaccessible, causing the transfer to fail -after a timeout. If the transfer includes a transmission, reduce the -RX threshold when the TX completes, otherwise use 1 for the whole -transfer (inefficient, but not catastrophic at SPI data rates). - -See: https://github.com/raspberrypi/linux/issues/5696 - -Signed-off-by: Phil Elwell ---- - drivers/spi/spi-dw-dma.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/spi/spi-dw-dma.c -+++ b/drivers/spi/spi-dw-dma.c -@@ -315,8 +315,10 @@ static void dw_spi_dma_tx_done(void *arg - struct dw_spi *dws = arg; - - clear_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy); -- if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy)) -+ if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy)) { -+ dw_writel(dws, DW_SPI_DMARDLR, 0); - return; -+ } - - complete(&dws->dma_completion); - } -@@ -642,6 +644,8 @@ static int dw_spi_dma_transfer(struct dw - - nents = max(xfer->tx_sg.nents, xfer->rx_sg.nents); - -+ dw_writel(dws, DW_SPI_DMARDLR, xfer->tx_buf ? (dws->rxburst - 1) : 0); -+ - /* - * Execute normal DMA-based transfer (which submits the Rx and Tx SG - * lists directly to the DMA engine at once) if either full hardware diff --git a/target/linux/bcm27xx/patches-6.6/950-1146-drivers-dwc_otg-use-C11-style-variable-array-declara.patch b/target/linux/bcm27xx/patches-6.6/950-1146-drivers-dwc_otg-use-C11-style-variable-array-declara.patch new file mode 100644 index 0000000000..b5f117f7f7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1146-drivers-dwc_otg-use-C11-style-variable-array-declara.patch @@ -0,0 +1,260 @@ +From 65fddc7301f52470fd846acede96d240a1902e67 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Fri, 5 Jul 2024 14:00:38 +0100 +Subject: [PATCH 1146/1215] drivers: dwc_otg: use C11 style variable array + declarations + +The kernel C standard changed in 5.18. + +Remove a layer of indirection around the FIQ bounce buffers, be consistent +with pointers to FIQ bounce buffers, and remove open-coded 32-bit clamping +of DMA addresses. + +Also remove a pointless fiq_state initialisation loop. + +Signed-off-by: Jonathan Bell +--- + drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 12 ++++---- + drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 8 ++--- + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 34 ++++++++++----------- + drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 4 +-- + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 4 +-- + 5 files changed, 28 insertions(+), 34 deletions(-) + +--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c +@@ -240,8 +240,8 @@ static int notrace fiq_increment_dma_buf + hcdma_data_t hcdma; + int i = st->channel[n].dma_info.index; + int len; +- struct fiq_dma_blob *blob = +- (struct fiq_dma_blob *)(uintptr_t)st->dma_base; ++ struct fiq_dma_channel *split_dma = ++ (struct fiq_dma_channel *)(uintptr_t)st->dma_base; + + len = fiq_get_xfer_len(st, n); + fiq_print(FIQDBG_INT, st, "LEN: %03d", len); +@@ -250,7 +250,7 @@ static int notrace fiq_increment_dma_buf + if (i > 6) + BUG(); + +- hcdma.d32 = (u32)(uintptr_t)&blob->channel[n].index[i].buf[0]; ++ hcdma.d32 = lower_32_bits((uintptr_t)&split_dma[n].index[i].buf[0]); + FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HC_DMA, hcdma.d32); + st->channel[n].dma_info.index = i; + return 0; +@@ -290,8 +290,8 @@ static int notrace fiq_iso_out_advance(s + hcsplt_data_t hcsplt; + hctsiz_data_t hctsiz; + hcdma_data_t hcdma; +- struct fiq_dma_blob *blob = +- (struct fiq_dma_blob *)(uintptr_t)st->dma_base; ++ struct fiq_dma_channel *split_dma = ++ (struct fiq_dma_channel *)(uintptr_t)st->dma_base; + int last = 0; + int i = st->channel[n].dma_info.index; + +@@ -303,7 +303,7 @@ static int notrace fiq_iso_out_advance(s + last = 1; + + /* New DMA address - address of bounce buffer referred to in index */ +- hcdma.d32 = (u32)(uintptr_t)blob->channel[n].index[i].buf; ++ hcdma.d32 = lower_32_bits((uintptr_t)&split_dma[n].index[i].buf[0]); + //hcdma.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HC_DMA); + //hcdma.d32 += st->channel[n].dma_info.slot_len[i]; + fiq_print(FIQDBG_INT, st, "LAST: %01d ", last); +--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h +@@ -263,10 +263,6 @@ struct fiq_dma_channel { + struct fiq_split_dma_slot index[6]; + } __attribute__((packed)); + +-struct fiq_dma_blob { +- struct fiq_dma_channel channel[0]; +-} __attribute__((packed)); +- + /** + * struct fiq_hs_isoc_info - USB2.0 isochronous data + * @iso_frame: Pointer to the array of OTG URB iso_frame_descs. +@@ -352,7 +348,7 @@ struct fiq_state { + mphi_regs_t mphi_regs; + void *dwc_regs_base; + dma_addr_t dma_base; +- struct fiq_dma_blob *fiq_dmab; ++ struct fiq_dma_channel *fiq_dmab; + void *dummy_send; + dma_addr_t dummy_send_dma; + gintmsk_data_t gintmsk_saved; +@@ -365,7 +361,7 @@ struct fiq_state { + char * buffer; + unsigned int bufsiz; + #endif +- struct fiq_channel_state channel[0]; ++ struct fiq_channel_state channel[]; + }; + + #ifdef CONFIG_ARM64 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -58,6 +58,7 @@ static int last_sel_trans_num_avail_hc_a + static int last_sel_trans_num_avail_hc_at_end = 0; + #endif /* DEBUG_HOST_CHANNELS */ + ++static_assert(FIQ_PASSTHROUGH == 0); + + dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) + { +@@ -876,7 +877,7 @@ void dwc_otg_hcd_power_up(void *ptr) + void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num) + { + struct fiq_channel_state *st = &hcd->fiq_state->channel[num]; +- struct fiq_dma_blob *blob = hcd->fiq_dmab; ++ struct fiq_dma_channel *split_dma = hcd->fiq_dmab; + int i; + + st->fsm = FIQ_PASSTHROUGH; +@@ -898,7 +899,7 @@ void dwc_otg_cleanup_fiq_channel(dwc_otg + st->hs_isoc_info.iso_desc = NULL; + st->hs_isoc_info.nrframes = 0; + +- DWC_MEMSET(&blob->channel[num].index[0], 0x6b, 1128); ++ DWC_MEMSET(&split_dma[num].index[0], 0x6b, 1128); + } + + /** +@@ -1045,9 +1046,6 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd + spin_lock_init(&hcd->fiq_state->lock); + #endif + +- for (i = 0; i < num_channels; i++) { +- hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH; +- } + hcd->fiq_state->dummy_send = DWC_DMA_ALLOC_ATOMIC(dev, 16, + &hcd->fiq_state->dummy_send_dma); + +@@ -1561,7 +1559,7 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h + int frame_length, i = 0; + uint8_t *ptr = NULL; + dwc_hc_t *hc = qh->channel; +- struct fiq_dma_blob *blob; ++ struct fiq_dma_channel *split_dma; + struct dwc_otg_hcd_iso_packet_desc *frame_desc; + + for (i = 0; i < 6; i++) { +@@ -1576,10 +1574,10 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h + * Pointer arithmetic on hcd->fiq_state->dma_base (a dma_addr_t) + * to point it to the correct offset in the allocated buffers. + */ +- blob = (struct fiq_dma_blob *) ++ split_dma = (struct fiq_dma_channel *) + (uintptr_t)hcd->fiq_state->dma_base; +- st->hcdma_copy.d32 =(u32)(uintptr_t) +- blob->channel[hc->hc_num].index[0].buf; ++ st->hcdma_copy.d32 = lower_32_bits((uintptr_t) ++ &split_dma[hc->hc_num].index[0].buf[0]); + + /* Calculate the max number of CSPLITS such that the FIQ can time out + * a transaction if it fails. +@@ -1600,7 +1598,7 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h + frame_length = frame_desc->length; + + /* Virtual address for bounce buffers */ +- blob = hcd->fiq_dmab; ++ split_dma = hcd->fiq_dmab; + + ptr = qtd->urb->buf + frame_desc->offset; + if (frame_length == 0) { +@@ -1613,11 +1611,11 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h + } else { + do { + if (frame_length <= 188) { +- dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, frame_length); ++ dwc_memcpy(&split_dma[hc->hc_num].index[i].buf[0], ptr, frame_length); + st->dma_info.slot_len[i] = frame_length; + ptr += frame_length; + } else { +- dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, 188); ++ dwc_memcpy(&split_dma[hc->hc_num].index[i].buf[0], ptr, 188); + st->dma_info.slot_len[i] = 188; + ptr += 188; + } +@@ -1634,10 +1632,10 @@ int fiq_fsm_setup_periodic_dma(dwc_otg_h + * dma_addr_t) to point it to the correct offset in the + * allocated buffers. + */ +- blob = (struct fiq_dma_blob *) ++ split_dma = (struct fiq_dma_channel *) + (uintptr_t)hcd->fiq_state->dma_base; +- st->hcdma_copy.d32 = (u32)(uintptr_t) +- blob->channel[hc->hc_num].index[0].buf; ++ st->hcdma_copy.d32 = lower_32_bits((uintptr_t) ++ &split_dma[hc->hc_num].index[0].buf[0]); + + /* fixup xfersize to the actual packet size */ + st->hctsiz_copy.b.pid = 0; +@@ -1917,14 +1915,14 @@ int fiq_fsm_queue_split_transaction(dwc_ + if (hc->align_buff) { + st->hcdma_copy.d32 = hc->align_buff; + } else { +- st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF); ++ st->hcdma_copy.d32 = lower_32_bits((uintptr_t)hc->xfer_buff); + } + } + } else { + if (hc->align_buff) { + st->hcdma_copy.d32 = hc->align_buff; + } else { +- st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF); ++ st->hcdma_copy.d32 = lower_32_bits((uintptr_t)hc->xfer_buff); + } + } + /* The FIQ depends upon no other interrupts being enabled except channel halt. +@@ -1944,7 +1942,7 @@ int fiq_fsm_queue_split_transaction(dwc_ + if (hc->align_buff) { + st->hcdma_copy.d32 = hc->align_buff; + } else { +- st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF); ++ st->hcdma_copy.d32 = lower_32_bits((uintptr_t)hc->xfer_buff); + } + } + DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32); +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +@@ -88,7 +88,7 @@ struct dwc_otg_hcd_urb { + uint32_t flags; + uint16_t interval; + struct dwc_otg_hcd_pipe_info pipe_info; +- struct dwc_otg_hcd_iso_packet_desc iso_descs[0]; ++ struct dwc_otg_hcd_iso_packet_desc iso_descs[]; + }; + + static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe) +@@ -592,7 +592,7 @@ struct dwc_otg_hcd { + struct fiq_state *fiq_state; + + /** Virtual address for split transaction DMA bounce buffers */ +- struct fiq_dma_blob *fiq_dmab; ++ struct fiq_dma_channel *fiq_dmab; + + #ifdef DEBUG + uint32_t frrem_samples; +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -2332,7 +2332,7 @@ void dwc_otg_fiq_unmangle_isoc(dwc_otg_h + int dwc_otg_fiq_unsetup_per_dma(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, dwc_otg_qtd_t *qtd, uint32_t num) + { + dwc_hc_t *hc = qh->channel; +- struct fiq_dma_blob *blob = hcd->fiq_dmab; ++ struct fiq_dma_channel *split_dma = hcd->fiq_dmab; + struct fiq_channel_state *st = &hcd->fiq_state->channel[num]; + uint8_t *ptr = NULL; + int index = 0, len = 0; +@@ -2352,7 +2352,7 @@ int dwc_otg_fiq_unsetup_per_dma(dwc_otg_ + + for (i = 0; i < st->dma_info.index; i++) { + len += st->dma_info.slot_len[i]; +- dwc_memcpy(ptr, &blob->channel[num].index[i].buf[0], st->dma_info.slot_len[i]); ++ dwc_memcpy(ptr, &split_dma[num].index[i].buf[0], st->dma_info.slot_len[i]); + ptr += st->dma_info.slot_len[i]; + } + return len; diff --git a/target/linux/bcm27xx/patches-6.6/950-1147-media-uapi-pixfmt-luma-Document-MIPI-CSI-2-packing.patch b/target/linux/bcm27xx/patches-6.6/950-1147-media-uapi-pixfmt-luma-Document-MIPI-CSI-2-packing.patch new file mode 100644 index 0000000000..14d0a79a73 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1147-media-uapi-pixfmt-luma-Document-MIPI-CSI-2-packing.patch @@ -0,0 +1,27 @@ +From 8dea9155ab081289edd618f8373d5f980d5bb664 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 23 Feb 2024 10:40:47 +0100 +Subject: [PATCH 1147/1215] media: uapi: pixfmt-luma: Document MIPI CSI-2 + packing + +The Y10P, Y12P and Y14P format variants are packed according to +the RAW10, RAW12 and RAW14 formats as defined by the MIPI CSI-2 +specification. Document it. + +Signed-off-by: Jacopo Mondi +Reviewed-by: Laurent Pinchart +Reviewed-by: Naushir Patuck +--- + Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst ++++ b/Documentation/userspace-api/media/v4l/pixfmt-yuv-luma.rst +@@ -161,3 +161,7 @@ are often referred to as greyscale forma + For Y012 and Y12 formats, Y012 places its data in the 12 high bits, with + padding zeros in the 4 low bits, in contrast to the Y12 format, which has + its padding located in the most significant bits of the 16 bit word. ++ ++ The 'P' variations of the Y10, Y12 and Y14 formats are packed according to ++ the RAW10, RAW12 and RAW14 packing scheme as defined by the MIPI CSI-2 ++ specification. diff --git a/target/linux/bcm27xx/patches-6.6/950-1148-media-uapi-Add-a-pixel-format-for-BGR48-and-RGB48.patch b/target/linux/bcm27xx/patches-6.6/950-1148-media-uapi-Add-a-pixel-format-for-BGR48-and-RGB48.patch new file mode 100644 index 0000000000..2f459044a3 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1148-media-uapi-Add-a-pixel-format-for-BGR48-and-RGB48.patch @@ -0,0 +1,101 @@ +From 814c088cb7183f79ba68c8f9459505e2ac4dde3a Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 26 Jan 2024 15:03:18 +0100 +Subject: [PATCH 1148/1215] media: uapi: Add a pixel format for BGR48 and RGB48 + +Add BGR48 and RGB48 16-bit per component image formats. + +Signed-off-by: Jacopo Mondi +Reviewed-by: Kieran Bingham +Reviewed-by: Naushir Patuck +--- + .../userspace-api/media/v4l/pixfmt-rgb.rst | 54 +++++++++++++++++++ + drivers/media/v4l2-core/v4l2-common.c | 2 + + include/uapi/linux/videodev2.h | 2 + + 3 files changed, 58 insertions(+) + +--- a/Documentation/userspace-api/media/v4l/pixfmt-rgb.rst ++++ b/Documentation/userspace-api/media/v4l/pixfmt-rgb.rst +@@ -996,6 +996,60 @@ arranged in little endian order. + + \normalsize + ++16 Bits Per Component ++===================== ++ ++These formats store an RGB triplet in six bytes, with 16 bits per component ++stored in memory in little endian byte order. They are named based on the order ++of the RGB components as stored in memory. For instance, RGB48 stores R\ ++:sub:`7:0` and R\ :sub:`15:8` in bytes 0 and 1 respectively. This differs from ++the DRM format nomenclature that instead uses the order of components as seen in ++the 48-bits little endian word. ++ ++.. raw:: latex ++ ++ \small ++ ++.. flat-table:: RGB Formats With 16 Bits Per Component ++ :header-rows: 1 ++ ++ * - Identifier ++ - Code ++ - Byte 0 ++ - Byte 1 ++ - Byte 2 ++ - Byte 3 ++ - Byte 4 ++ - Byte 5 ++ ++ * .. _V4L2-PIX-FMT-BGR48: ++ ++ - ``V4L2_PIX_FMT_BGR48`` ++ - 'BGR6' ++ ++ - B\ :sub:`7-0` ++ - B\ :sub:`15-8` ++ - G\ :sub:`7-0` ++ - G\ :sub:`15-8` ++ - R\ :sub:`7-0` ++ - R\ :sub:`15-8` ++ ++ * .. _V4L2-PIX-FMT-RGB48: ++ ++ - ``V4L2_PIX_FMT_RGB48`` ++ - 'RGB6' ++ ++ - R\ :sub:`7-0` ++ - R\ :sub:`15-8` ++ - G\ :sub:`7-0` ++ - G\ :sub:`15-8` ++ - B\ :sub:`7-0` ++ - B\ :sub:`15-8` ++ ++.. raw:: latex ++ ++ \normalsize ++ + Deprecated RGB Formats + ====================== + +--- a/drivers/media/v4l2-core/v4l2-common.c ++++ b/drivers/media/v4l2-core/v4l2-common.c +@@ -253,6 +253,8 @@ const struct v4l2_format_info *v4l2_form + { .format = V4L2_PIX_FMT_RGB555, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 2, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR666, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 4, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_BGR48_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, ++ { .format = V4L2_PIX_FMT_BGR48, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, ++ { .format = V4L2_PIX_FMT_RGB48, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 6, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + { .format = V4L2_PIX_FMT_ABGR64_12, .pixel_enc = V4L2_PIXEL_ENC_RGB, .mem_planes = 1, .comp_planes = 1, .bpp = { 8, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, + + /* YUV packed formats */ +--- a/include/uapi/linux/videodev2.h ++++ b/include/uapi/linux/videodev2.h +@@ -587,6 +587,8 @@ struct v4l2_pix_format { + + /* RGB formats (6 or 8 bytes per pixel) */ + #define V4L2_PIX_FMT_BGR48_12 v4l2_fourcc('B', '3', '1', '2') /* 48 BGR 12-bit per component */ ++#define V4L2_PIX_FMT_BGR48 v4l2_fourcc('B', 'G', 'R', '6') /* 48 BGR 16-bit per component */ ++#define V4L2_PIX_FMT_RGB48 v4l2_fourcc('R', 'G', 'B', '6') /* 48 RGB 16-bit per component */ + #define V4L2_PIX_FMT_ABGR64_12 v4l2_fourcc('B', '4', '1', '2') /* 64 BGRA 12-bit per component */ + + /* RGB formats (6 bytes per pixel) */ diff --git a/target/linux/bcm27xx/patches-6.6/950-1149-media-uapi-Add-Raspberry-Pi-PiSP-Back-End-uAPI.patch b/target/linux/bcm27xx/patches-6.6/950-1149-media-uapi-Add-Raspberry-Pi-PiSP-Back-End-uAPI.patch new file mode 100644 index 0000000000..a59bcb1e97 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1149-media-uapi-Add-Raspberry-Pi-PiSP-Back-End-uAPI.patch @@ -0,0 +1,1171 @@ +From be6996ad702fac96b36ea209ae04a71bd1c6e1d4 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 24 May 2024 15:18:21 +0200 +Subject: [PATCH 1149/1215] media: uapi: Add Raspberry Pi PiSP Back End uAPI + +Add the Raspberry Pi PiSP Back End uAPI header. + +The header defines the data type used to configure the PiSP Back End +ISP. + +The detailed description of the types and of the ISP configuration +procedure is available at +https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf + +Signed-off-by: Jacopo Mondi +--- + MAINTAINERS | 7 + + .../linux/media/raspberrypi/pisp_be_config.h | 927 ++++++++++++++++++ + .../linux/media/raspberrypi/pisp_common.h | 199 ++++ + 3 files changed, 1133 insertions(+) + create mode 100644 include/uapi/linux/media/raspberrypi/pisp_be_config.h + create mode 100644 include/uapi/linux/media/raspberrypi/pisp_common.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -18032,6 +18032,13 @@ L: linux-wireless@vger.kernel.org + S: Orphan + F: drivers/net/wireless/legacy/ray* + ++RASPBERRY PI PISP BACK END ++M: Jacopo Mondi ++L: Raspberry Pi Kernel Maintenance ++L: linux-media@vger.kernel.org ++S: Maintained ++F: include/uapi/linux/media/raspberrypi/ ++ + RC-CORE / LIRC FRAMEWORK + M: Sean Young + L: linux-media@vger.kernel.org +--- /dev/null ++++ b/include/uapi/linux/media/raspberrypi/pisp_be_config.h +@@ -0,0 +1,927 @@ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ ++/* ++ * PiSP Back End configuration definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd ++ * ++ */ ++#ifndef _UAPI_PISP_BE_CONFIG_H_ ++#define _UAPI_PISP_BE_CONFIG_H_ ++ ++#include ++ ++#include "pisp_common.h" ++ ++/* byte alignment for inputs */ ++#define PISP_BACK_END_INPUT_ALIGN 4u ++/* alignment for compressed inputs */ ++#define PISP_BACK_END_COMPRESSED_ALIGN 8u ++/* minimum required byte alignment for outputs */ ++#define PISP_BACK_END_OUTPUT_MIN_ALIGN 16u ++/* preferred byte alignment for outputs */ ++#define PISP_BACK_END_OUTPUT_MAX_ALIGN 64u ++ ++/* minimum allowed tile width anywhere in the pipeline */ ++#define PISP_BACK_END_MIN_TILE_WIDTH 16u ++/* minimum allowed tile width anywhere in the pipeline */ ++#define PISP_BACK_END_MIN_TILE_HEIGHT 16u ++ ++#define PISP_BACK_END_NUM_OUTPUTS 2 ++#define PISP_BACK_END_HOG_OUTPUT 1 ++ ++#define PISP_BACK_END_NUM_TILES 64 ++ ++enum pisp_be_bayer_enable { ++ PISP_BE_BAYER_ENABLE_INPUT = 0x000001, ++ PISP_BE_BAYER_ENABLE_DECOMPRESS = 0x000002, ++ PISP_BE_BAYER_ENABLE_DPC = 0x000004, ++ PISP_BE_BAYER_ENABLE_GEQ = 0x000008, ++ PISP_BE_BAYER_ENABLE_TDN_INPUT = 0x000010, ++ PISP_BE_BAYER_ENABLE_TDN_DECOMPRESS = 0x000020, ++ PISP_BE_BAYER_ENABLE_TDN = 0x000040, ++ PISP_BE_BAYER_ENABLE_TDN_COMPRESS = 0x000080, ++ PISP_BE_BAYER_ENABLE_TDN_OUTPUT = 0x000100, ++ PISP_BE_BAYER_ENABLE_SDN = 0x000200, ++ PISP_BE_BAYER_ENABLE_BLC = 0x000400, ++ PISP_BE_BAYER_ENABLE_STITCH_INPUT = 0x000800, ++ PISP_BE_BAYER_ENABLE_STITCH_DECOMPRESS = 0x001000, ++ PISP_BE_BAYER_ENABLE_STITCH = 0x002000, ++ PISP_BE_BAYER_ENABLE_STITCH_COMPRESS = 0x004000, ++ PISP_BE_BAYER_ENABLE_STITCH_OUTPUT = 0x008000, ++ PISP_BE_BAYER_ENABLE_WBG = 0x010000, ++ PISP_BE_BAYER_ENABLE_CDN = 0x020000, ++ PISP_BE_BAYER_ENABLE_LSC = 0x040000, ++ PISP_BE_BAYER_ENABLE_TONEMAP = 0x080000, ++ PISP_BE_BAYER_ENABLE_CAC = 0x100000, ++ PISP_BE_BAYER_ENABLE_DEBIN = 0x200000, ++ PISP_BE_BAYER_ENABLE_DEMOSAIC = 0x400000, ++}; ++ ++enum pisp_be_rgb_enable { ++ PISP_BE_RGB_ENABLE_INPUT = 0x000001, ++ PISP_BE_RGB_ENABLE_CCM = 0x000002, ++ PISP_BE_RGB_ENABLE_SAT_CONTROL = 0x000004, ++ PISP_BE_RGB_ENABLE_YCBCR = 0x000008, ++ PISP_BE_RGB_ENABLE_FALSE_COLOUR = 0x000010, ++ PISP_BE_RGB_ENABLE_SHARPEN = 0x000020, ++ /* Preferred colours would occupy 0x000040 */ ++ PISP_BE_RGB_ENABLE_YCBCR_INVERSE = 0x000080, ++ PISP_BE_RGB_ENABLE_GAMMA = 0x000100, ++ PISP_BE_RGB_ENABLE_CSC0 = 0x000200, ++ PISP_BE_RGB_ENABLE_CSC1 = 0x000400, ++ PISP_BE_RGB_ENABLE_DOWNSCALE0 = 0x001000, ++ PISP_BE_RGB_ENABLE_DOWNSCALE1 = 0x002000, ++ PISP_BE_RGB_ENABLE_RESAMPLE0 = 0x008000, ++ PISP_BE_RGB_ENABLE_RESAMPLE1 = 0x010000, ++ PISP_BE_RGB_ENABLE_OUTPUT0 = 0x040000, ++ PISP_BE_RGB_ENABLE_OUTPUT1 = 0x080000, ++ PISP_BE_RGB_ENABLE_HOG = 0x200000 ++}; ++ ++#define PISP_BE_RGB_ENABLE_CSC(i) (PISP_BE_RGB_ENABLE_CSC0 << (i)) ++#define PISP_BE_RGB_ENABLE_DOWNSCALE(i) (PISP_BE_RGB_ENABLE_DOWNSCALE0 << (i)) ++#define PISP_BE_RGB_ENABLE_RESAMPLE(i) (PISP_BE_RGB_ENABLE_RESAMPLE0 << (i)) ++#define PISP_BE_RGB_ENABLE_OUTPUT(i) (PISP_BE_RGB_ENABLE_OUTPUT0 << (i)) ++ ++/* ++ * We use the enable flags to show when blocks are "dirty", but we need some ++ * extra ones too. ++ */ ++enum pisp_be_dirty { ++ PISP_BE_DIRTY_GLOBAL = 0x0001, ++ PISP_BE_DIRTY_SH_FC_COMBINE = 0x0002, ++ PISP_BE_DIRTY_CROP = 0x0004 ++}; ++ ++/** ++ * struct pisp_be_global_config - PiSP global enable bitmaps ++ * @bayer_enables: Bayer input enable flags ++ * @rgb_enables: RGB output enable flags ++ * @bayer_order: Bayer input format ordering ++ * @pad: Padding bytes ++ */ ++struct pisp_be_global_config { ++ __u32 bayer_enables; ++ __u32 rgb_enables; ++ __u8 bayer_order; ++ __u8 pad[3]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_input_buffer_config - PiSP Back End input buffer ++ * @addr: Input buffer address ++ */ ++struct pisp_be_input_buffer_config { ++ /* low 32 bits followed by high 32 bits (for each of up to 3 planes) */ ++ __u32 addr[3][2]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_dpc_config - PiSP Back End DPC config ++ * ++ * Defective Pixel Correction configuration ++ * ++ * @coeff_level: Coefficient for the darkest neighbouring pixel value ++ * @coeff_range: Coefficient for the range of pixels for this Bayer channel ++ * @pad: Padding byte ++ * @flags: DPC configuration flags ++ */ ++struct pisp_be_dpc_config { ++ __u8 coeff_level; ++ __u8 coeff_range; ++ __u8 pad; ++#define PISP_BE_DPC_FLAG_FOLDBACK 1 ++ __u8 flags; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_geq_config - PiSP Back End GEQ config ++ * ++ * Green Equalisation configuration ++ * ++ * @offset: Offset value for threshold calculation ++ * @slope_sharper: Slope/Sharper configuration ++ * @min: Minimum value the threshold may have ++ * @max: Maximum value the threshold may have ++ */ ++struct pisp_be_geq_config { ++ __u16 offset; ++#define PISP_BE_GEQ_SHARPER BIT(15) ++#define PISP_BE_GEQ_SLOPE ((1 << 10) - 1) ++ /* top bit is the "sharper" flag, slope value is bottom 10 bits */ ++ __u16 slope_sharper; ++ __u16 min; ++ __u16 max; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_tdn_input_buffer_config - PiSP Back End TDN input buffer ++ * @addr: TDN input buffer address ++ */ ++struct pisp_be_tdn_input_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ __u32 addr[2]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_tdn_config - PiSP Back End TDN config ++ * ++ * Temporal Denoise configuration ++ * ++ * @black_level: Black level value subtracted from pixels ++ * @ratio: Multiplier for the LTA input frame ++ * @noise_constant: Constant offset value used in noise estimation ++ * @noise_slope: Noise estimation multiplier ++ * @threshold: Threshold for TDN operations ++ * @reset: Disable TDN operations ++ * @pad: Padding byte ++ */ ++struct pisp_be_tdn_config { ++ __u16 black_level; ++ __u16 ratio; ++ __u16 noise_constant; ++ __u16 noise_slope; ++ __u16 threshold; ++ __u8 reset; ++ __u8 pad; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_tdn_output_buffer_config - PiSP Back End TDN output buffer ++ * @addr: TDN output buffer address ++ */ ++struct pisp_be_tdn_output_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ __u32 addr[2]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_sdn_config - PiSP Back End SDN config ++ * ++ * Spatial Denoise configuration ++ * ++ * @black_level: Black level subtracted from pixel for noise estimation ++ * @leakage: Proportion of the original undenoised value to mix in ++ * denoised output ++ * @pad: Padding byte ++ * @noise_constant: Noise constant used for noise estimation ++ * @noise_slope: Noise slope value used for noise estimation ++ * @noise_constant2: Second noise constant used for noise estimation ++ * @noise_slope2: Second slope value used for noise estimation ++ */ ++struct pisp_be_sdn_config { ++ __u16 black_level; ++ __u8 leakage; ++ __u8 pad; ++ __u16 noise_constant; ++ __u16 noise_slope; ++ __u16 noise_constant2; ++ __u16 noise_slope2; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_stitch_input_buffer_config - PiSP Back End Stitch input ++ * @addr: Stitch input buffer address ++ */ ++struct pisp_be_stitch_input_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ __u32 addr[2]; ++} __attribute__((packed)); ++ ++#define PISP_BE_STITCH_STREAMING_LONG 0x8000 ++#define PISP_BE_STITCH_EXPOSURE_RATIO_MASK 0x7fff ++ ++/** ++ * struct pisp_be_stitch_config - PiSP Back End Stitch config ++ * ++ * Stitch block configuration ++ * ++ * @threshold_lo: Low threshold value ++ * @threshold_diff_power: Low and high threshold difference ++ * @pad: Padding bytes ++ * @exposure_ratio: Multiplier to convert long exposure pixels into ++ * short exposure pixels ++ * @motion_threshold_256: Motion threshold above which short exposure ++ * pixels are used ++ * @motion_threshold_recip: Reciprocal of motion_threshold_256 value ++ */ ++struct pisp_be_stitch_config { ++ __u16 threshold_lo; ++ __u8 threshold_diff_power; ++ __u8 pad; ++ ++ /* top bit indicates whether streaming input is the long exposure */ ++ __u16 exposure_ratio; ++ ++ __u8 motion_threshold_256; ++ __u8 motion_threshold_recip; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_stitch_output_buffer_config - PiSP Back End Stitch output ++ * @addr: Stitch input buffer address ++ */ ++struct pisp_be_stitch_output_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ __u32 addr[2]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_cdn_config - PiSP Back End CDN config ++ * ++ * Colour Denoise configuration ++ * ++ * @thresh: Constant for noise estimation ++ * @iir_strength: Relative strength of the IIR part of the filter ++ * @g_adjust: Proportion of the change assigned to the G channel ++ */ ++struct pisp_be_cdn_config { ++ __u16 thresh; ++ __u8 iir_strength; ++ __u8 g_adjust; ++} __attribute__((packed)); ++ ++#define PISP_BE_LSC_LOG_GRID_SIZE 5 ++#define PISP_BE_LSC_GRID_SIZE (1 << PISP_BE_LSC_LOG_GRID_SIZE) ++#define PISP_BE_LSC_STEP_PRECISION 18 ++ ++/** ++ * struct pisp_be_lsc_config - PiSP Back End LSC config ++ * ++ * Lens Shading Correction configuration ++ * ++ * @grid_step_x: Reciprocal of cell size width ++ * @grid_step_y: Reciprocal of cell size height ++ * @lut_packed: Jointly-coded RGB gains for each LSC grid ++ */ ++struct pisp_be_lsc_config { ++ /* (1<<18) / grid_cell_width */ ++ __u16 grid_step_x; ++ /* (1<<18) / grid_cell_height */ ++ __u16 grid_step_y; ++ /* RGB gains jointly encoded in 32 bits */ ++#define PISP_BE_LSC_LUT_SIZE (PISP_BE_LSC_GRID_SIZE + 1) ++ __u32 lut_packed[PISP_BE_LSC_LUT_SIZE][PISP_BE_LSC_LUT_SIZE]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_lsc_extra - PiSP Back End LSC Extra config ++ * @offset_x: Horizontal offset into the LSC table of this tile ++ * @offset_y: Vertical offset into the LSC table of this tile ++ */ ++struct pisp_be_lsc_extra { ++ __u16 offset_x; ++ __u16 offset_y; ++} __attribute__((packed)); ++ ++#define PISP_BE_CAC_LOG_GRID_SIZE 3 ++#define PISP_BE_CAC_GRID_SIZE (1 << PISP_BE_CAC_LOG_GRID_SIZE) ++#define PISP_BE_CAC_STEP_PRECISION 20 ++ ++/** ++ * struct pisp_be_cac_config - PiSP Back End CAC config ++ * ++ * Chromatic Aberration Correction config ++ * ++ * @grid_step_x: Reciprocal of cell size width ++ * @grid_step_y: Reciprocal of cell size height ++ * @lut: Pixel shift for the CAC grid ++ */ ++struct pisp_be_cac_config { ++ /* (1<<20) / grid_cell_width */ ++ __u16 grid_step_x; ++ /* (1<<20) / grid_cell_height */ ++ __u16 grid_step_y; ++ /* [gridy][gridx][rb][xy] */ ++#define PISP_BE_CAC_LUT_SIZE (PISP_BE_CAC_GRID_SIZE + 1) ++ __s8 lut[PISP_BE_CAC_LUT_SIZE][PISP_BE_CAC_LUT_SIZE][2][2]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_cac_extra - PiSP Back End CAC extra config ++ * @offset_x: Horizontal offset into the CAC table of this tile ++ * @offset_y: Horizontal offset into the CAC table of this tile ++ */ ++struct pisp_be_cac_extra { ++ __u16 offset_x; ++ __u16 offset_y; ++} __attribute__((packed)); ++ ++#define PISP_BE_DEBIN_NUM_COEFFS 4 ++ ++/** ++ * struct pisp_be_debin_config - PiSP Back End Debin config ++ * ++ * Debinning configuration ++ * ++ * @coeffs: Filter coefficients for debinning ++ * @h_enable: Horizontal debinning enable ++ * @v_enable: Vertical debinning enable ++ * @pad: Padding bytes ++ */ ++struct pisp_be_debin_config { ++ __s8 coeffs[PISP_BE_DEBIN_NUM_COEFFS]; ++ __s8 h_enable; ++ __s8 v_enable; ++ __s8 pad[2]; ++} __attribute__((packed)); ++ ++#define PISP_BE_TONEMAP_LUT_SIZE 64 ++ ++/** ++ * struct pisp_be_tonemap_config - PiSP Back End Tonemap config ++ * ++ * Tonemapping configuration ++ * ++ * @detail_constant: Constant value for threshold calculation ++ * @detail_slope: Slope value for threshold calculation ++ * @iir_strength: Relative strength of the IIR fiter ++ * @strength: Strength factor ++ * @lut: Look-up table for tonemap curve ++ */ ++struct pisp_be_tonemap_config { ++ __u16 detail_constant; ++ __u16 detail_slope; ++ __u16 iir_strength; ++ __u16 strength; ++ __u32 lut[PISP_BE_TONEMAP_LUT_SIZE]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_demosaic_config - PiSP Back End Demosaic config ++ * ++ * Demosaic configuration ++ * ++ * @sharper: Use other Bayer channels to increase sharpness ++ * @fc_mode: Built-in false colour suppression mode ++ * @pad: Padding bytes ++ */ ++struct pisp_be_demosaic_config { ++ __u8 sharper; ++ __u8 fc_mode; ++ __u8 pad[2]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_ccm_config - PiSP Back End CCM config ++ * ++ * Colour Correction Matrix configuration ++ * ++ * @coeffs: Matrix coefficients ++ * @pad: Padding bytes ++ * @offsets: Offsets triplet ++ */ ++struct pisp_be_ccm_config { ++ __s16 coeffs[9]; ++ __u8 pad[2]; ++ __s32 offsets[3]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_sat_control_config - PiSP Back End SAT config ++ * ++ * Saturation Control configuration ++ * ++ * @shift_r: Left shift for Red colour channel ++ * @shift_g: Left shift for Green colour channel ++ * @shift_b: Left shift for Blue colour channel ++ * @pad: Padding byte ++ */ ++struct pisp_be_sat_control_config { ++ __u8 shift_r; ++ __u8 shift_g; ++ __u8 shift_b; ++ __u8 pad; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_false_colour_config - PiSP Back End False Colour config ++ * ++ * False Colour configuration ++ * ++ * @distance: Distance of neighbouring pixels, either 1 or 2 ++ * @pad: Padding bytes ++ */ ++struct pisp_be_false_colour_config { ++ __u8 distance; ++ __u8 pad[3]; ++} __attribute__((packed)); ++ ++#define PISP_BE_SHARPEN_SIZE 5 ++#define PISP_BE_SHARPEN_FUNC_NUM_POINTS 9 ++ ++/** ++ * struct pisp_be_sharpen_config - PiSP Back End Sharpening config ++ * ++ * Sharpening configuration ++ * ++ * @kernel0: Coefficient for filter 0 ++ * @pad0: Padding byte ++ * @kernel1: Coefficient for filter 1 ++ * @pad1: Padding byte ++ * @kernel2: Coefficient for filter 2 ++ * @pad2: Padding byte ++ * @kernel3: Coefficient for filter 3 ++ * @pad3: Padding byte ++ * @kernel4: Coefficient for filter 4 ++ * @pad4: Padding byte ++ * @threshold_offset0: Offset for filter 0 response calculation ++ * @threshold_slope0: Slope multiplier for the filter 0 response calculation ++ * @scale0: Scale factor for filter 0 response calculation ++ * @pad5: Padding byte ++ * @threshold_offset1: Offset for filter 0 response calculation ++ * @threshold_slope1: Slope multiplier for the filter 0 response calculation ++ * @scale1: Scale factor for filter 0 response calculation ++ * @pad6: Padding byte ++ * @threshold_offset2: Offset for filter 0 response calculation ++ * @threshold_slope2: Slope multiplier for the filter 0 response calculation ++ * @scale2: Scale factor for filter 0 response calculation ++ * @pad7: Padding byte ++ * @threshold_offset3: Offset for filter 0 response calculation ++ * @threshold_slope3: Slope multiplier for the filter 0 response calculation ++ * @scale3: Scale factor for filter 0 response calculation ++ * @pad8: Padding byte ++ * @threshold_offset4: Offset for filter 0 response calculation ++ * @threshold_slope4: Slope multiplier for the filter 0 response calculation ++ * @scale4: Scale factor for filter 0 response calculation ++ * @pad9: Padding byte ++ * @positive_strength: Factor to scale the positive sharpening strength ++ * @positive_pre_limit: Maximum allowed possible positive sharpening value ++ * @positive_func: Gain factor applied to positive sharpening response ++ * @positive_limit: Final gain factor applied to positive sharpening ++ * @negative_strength: Factor to scale the negative sharpening strength ++ * @negative_pre_limit: Maximum allowed possible negative sharpening value ++ * @negative_func: Gain factor applied to negative sharpening response ++ * @negative_limit: Final gain factor applied to negative sharpening ++ * @enables: Filter enable mask ++ * @white: White output pixel filter mask ++ * @black: Black output pixel filter mask ++ * @grey: Grey output pixel filter mask ++ */ ++struct pisp_be_sharpen_config { ++ __s8 kernel0[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ __s8 pad0[3]; ++ __s8 kernel1[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ __s8 pad1[3]; ++ __s8 kernel2[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ __s8 pad2[3]; ++ __s8 kernel3[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ __s8 pad3[3]; ++ __s8 kernel4[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; ++ __s8 pad4[3]; ++ __u16 threshold_offset0; ++ __u16 threshold_slope0; ++ __u16 scale0; ++ __u16 pad5; ++ __u16 threshold_offset1; ++ __u16 threshold_slope1; ++ __u16 scale1; ++ __u16 pad6; ++ __u16 threshold_offset2; ++ __u16 threshold_slope2; ++ __u16 scale2; ++ __u16 pad7; ++ __u16 threshold_offset3; ++ __u16 threshold_slope3; ++ __u16 scale3; ++ __u16 pad8; ++ __u16 threshold_offset4; ++ __u16 threshold_slope4; ++ __u16 scale4; ++ __u16 pad9; ++ __u16 positive_strength; ++ __u16 positive_pre_limit; ++ __u16 positive_func[PISP_BE_SHARPEN_FUNC_NUM_POINTS]; ++ __u16 positive_limit; ++ __u16 negative_strength; ++ __u16 negative_pre_limit; ++ __u16 negative_func[PISP_BE_SHARPEN_FUNC_NUM_POINTS]; ++ __u16 negative_limit; ++ __u8 enables; ++ __u8 white; ++ __u8 black; ++ __u8 grey; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_sh_fc_combine_config - PiSP Back End Sharpening and ++ * False Colour config ++ * ++ * Sharpening and False Colour configuration ++ * ++ * @y_factor: Control amount of desaturation of pixels being darkened ++ * @c1_factor: Control amount of brightening of a pixel for the Cb ++ * channel ++ * @c2_factor: Control amount of brightening of a pixel for the Cr ++ * channel ++ * @pad: Padding byte ++ */ ++struct pisp_be_sh_fc_combine_config { ++ __u8 y_factor; ++ __u8 c1_factor; ++ __u8 c2_factor; ++ __u8 pad; ++} __attribute__((packed)); ++ ++#define PISP_BE_GAMMA_LUT_SIZE 64 ++ ++/** ++ * struct pisp_be_gamma_config - PiSP Back End Gamma configuration ++ * @lut: Gamma curve look-up table ++ */ ++struct pisp_be_gamma_config { ++ __u32 lut[PISP_BE_GAMMA_LUT_SIZE]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_crop_config - PiSP Back End Crop config ++ * ++ * Crop configuration ++ * ++ * @offset_x: Number of pixels cropped from the left of the tile ++ * @offset_y: Number of pixels cropped from the top of the tile ++ * @width: Width of the cropped tile output ++ * @height: Height of the cropped tile output ++ */ ++struct pisp_be_crop_config { ++ __u16 offset_x, offset_y; ++ __u16 width, height; ++} __attribute__((packed)); ++ ++#define PISP_BE_RESAMPLE_FILTER_SIZE 96 ++ ++/** ++ * struct pisp_be_resample_config - PiSP Back End Resampling config ++ * ++ * Resample configuration ++ * ++ * @scale_factor_h: Horizontal scale factor ++ * @scale_factor_v: Vertical scale factor ++ * @coef: Resample coefficients ++ */ ++struct pisp_be_resample_config { ++ __u16 scale_factor_h, scale_factor_v; ++ __s16 coef[PISP_BE_RESAMPLE_FILTER_SIZE]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_resample_extra - PiSP Back End Resample config ++ * ++ * Resample configuration ++ * ++ * @scaled_width: Width in pixels of the scaled output ++ * @scaled_height: Height in pixels of the scaled output ++ * @initial_phase_h: Initial horizontal phase ++ * @initial_phase_v: Initial vertical phase ++ */ ++struct pisp_be_resample_extra { ++ __u16 scaled_width; ++ __u16 scaled_height; ++ __s16 initial_phase_h[3]; ++ __s16 initial_phase_v[3]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_downscale_config - PiSP Back End Downscale config ++ * ++ * Downscale configuration ++ * ++ * @scale_factor_h: Horizontal scale factor ++ * @scale_factor_v: Vertical scale factor ++ * @scale_recip_h: Horizontal reciprocal factor ++ * @scale_recip_v: Vertical reciprocal factor ++ */ ++struct pisp_be_downscale_config { ++ __u16 scale_factor_h; ++ __u16 scale_factor_v; ++ __u16 scale_recip_h; ++ __u16 scale_recip_v; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_downscale_extra - PiSP Back End Downscale Extra config ++ * @scaled_width: Scaled image width ++ * @scaled_height: Scaled image height ++ */ ++struct pisp_be_downscale_extra { ++ __u16 scaled_width; ++ __u16 scaled_height; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_hog_config - PiSP Back End HOG config ++ * ++ * Histogram of Oriented Gradients configuration ++ * ++ * @compute_signed: Set 0 for unsigned gradients, 1 for signed ++ * @channel_mix: Channels proportions to use ++ * @stride: Stride in bytes between blocks directly below ++ */ ++struct pisp_be_hog_config { ++ __u8 compute_signed; ++ __u8 channel_mix[3]; ++ __u32 stride; ++} __attribute__((packed)); ++ ++struct pisp_be_axi_config { ++ __u8 r_qos; /* Read QoS */ ++ __u8 r_cache_prot; /* Read { prot[2:0], cache[3:0] } */ ++ __u8 w_qos; /* Write QoS */ ++ __u8 w_cache_prot; /* Write { prot[2:0], cache[3:0] } */ ++} __attribute__((packed)); ++ ++/** ++ * enum pisp_be_transform - PiSP Back End Transform flags ++ * @PISP_BE_TRANSFORM_NONE: No transform ++ * @PISP_BE_TRANSFORM_HFLIP: Horizontal flip ++ * @PISP_BE_TRANSFORM_VFLIP: Vertical flip ++ * @PISP_BE_TRANSFORM_ROT180: 180 degress rotation ++ */ ++enum pisp_be_transform { ++ PISP_BE_TRANSFORM_NONE = 0x0, ++ PISP_BE_TRANSFORM_HFLIP = 0x1, ++ PISP_BE_TRANSFORM_VFLIP = 0x2, ++ PISP_BE_TRANSFORM_ROT180 = ++ (PISP_BE_TRANSFORM_HFLIP | PISP_BE_TRANSFORM_VFLIP) ++}; ++ ++struct pisp_be_output_format_config { ++ struct pisp_image_format_config image; ++ __u8 transform; ++ __u8 pad[3]; ++ __u16 lo; ++ __u16 hi; ++ __u16 lo2; ++ __u16 hi2; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_output_buffer_config - PiSP Back End Output buffer ++ * @addr: Output buffer address ++ */ ++struct pisp_be_output_buffer_config { ++ /* low 32 bits followed by high 32 bits (for each of 3 planes) */ ++ __u32 addr[3][2]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_hog_buffer_config - PiSP Back End HOG buffer ++ * @addr: HOG buffer address ++ */ ++struct pisp_be_hog_buffer_config { ++ /* low 32 bits followed by high 32 bits */ ++ __u32 addr[2]; ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_config - RaspberryPi PiSP Back End Processing configuration ++ * ++ * @global: Global PiSP configuration ++ * @input_format: Input image format ++ * @decompress: Decompress configuration ++ * @dpc: Defective Pixel Correction configuration ++ * @geq: Green Equalisation configuration ++ * @tdn_input_format: Temporal Denoise input format ++ * @tdn_decompress: Temporal Denoise decompress configuration ++ * @tdn: Temporal Denoise configuration ++ * @tdn_compress: Temporal Denoise compress configuration ++ * @tdn_output_format: Temporal Denoise output format ++ * @sdn: Spatial Denoise configuration ++ * @blc: Black Level Correction configuration ++ * @stitch_compress: Stitch compress configuration ++ * @stitch_output_format: Stitch output format ++ * @stitch_input_format: Stitch input format ++ * @stitch_decompress: Stitch decompress configuration ++ * @stitch: Stitch configuration ++ * @lsc: Lens Shading Correction configuration ++ * @wbg: White Balance Gain configuration ++ * @cdn: Colour Denoise configuration ++ * @cac: Colour Aberration Correction configuration ++ * @debin: Debinning configuration ++ * @tonemap: Tonemapping configuration ++ * @demosaic: Demosaicing configuration ++ * @ccm: Colour Correction Matrix configuration ++ * @sat_control: Saturation Control configuration ++ * @ycbcr: YCbCr colour correction configuration ++ * @sharpen: Sharpening configuration ++ * @false_colour: False colour correction ++ * @sh_fc_combine: Sharpening and False Colour correction ++ * @ycbcr_inverse: Inverse YCbCr colour correction ++ * @gamma: Gamma curve configuration ++ * @csc: Color Space Conversion configuration ++ * @downscale: Downscale configuration ++ * @resample: Resampling configuration ++ * @output_format: Output format configuration ++ * @hog: HOG configuration ++ */ ++struct pisp_be_config { ++ struct pisp_be_global_config global; ++ struct pisp_image_format_config input_format; ++ struct pisp_decompress_config decompress; ++ struct pisp_be_dpc_config dpc; ++ struct pisp_be_geq_config geq; ++ struct pisp_image_format_config tdn_input_format; ++ struct pisp_decompress_config tdn_decompress; ++ struct pisp_be_tdn_config tdn; ++ struct pisp_compress_config tdn_compress; ++ struct pisp_image_format_config tdn_output_format; ++ struct pisp_be_sdn_config sdn; ++ struct pisp_bla_config blc; ++ struct pisp_compress_config stitch_compress; ++ struct pisp_image_format_config stitch_output_format; ++ struct pisp_image_format_config stitch_input_format; ++ struct pisp_decompress_config stitch_decompress; ++ struct pisp_be_stitch_config stitch; ++ struct pisp_be_lsc_config lsc; ++ struct pisp_wbg_config wbg; ++ struct pisp_be_cdn_config cdn; ++ struct pisp_be_cac_config cac; ++ struct pisp_be_debin_config debin; ++ struct pisp_be_tonemap_config tonemap; ++ struct pisp_be_demosaic_config demosaic; ++ struct pisp_be_ccm_config ccm; ++ struct pisp_be_sat_control_config sat_control; ++ struct pisp_be_ccm_config ycbcr; ++ struct pisp_be_sharpen_config sharpen; ++ struct pisp_be_false_colour_config false_colour; ++ struct pisp_be_sh_fc_combine_config sh_fc_combine; ++ struct pisp_be_ccm_config ycbcr_inverse; ++ struct pisp_be_gamma_config gamma; ++ struct pisp_be_ccm_config csc[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_downscale_config downscale[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_resample_config resample[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_output_format_config ++ output_format[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_hog_config hog; ++} __attribute__((packed)); ++ ++/** ++ * enum pisp_tile_edge - PiSP Back End Tile position ++ * @PISP_LEFT_EDGE: Left edge tile ++ * @PISP_RIGHT_EDGE: Right edge tile ++ * @PISP_TOP_EDGE: Top edge tile ++ * @PISP_BOTTOM_EDGE: Bottom edge tile ++ */ ++enum pisp_tile_edge { ++ PISP_LEFT_EDGE = (1 << 0), ++ PISP_RIGHT_EDGE = (1 << 1), ++ PISP_TOP_EDGE = (1 << 2), ++ PISP_BOTTOM_EDGE = (1 << 3) ++}; ++ ++/** ++ * struct pisp_tile - Raspberry Pi PiSP Back End tile configuration ++ * ++ * Tile parameters: each set of tile parameters is a 160-bytes block of data ++ * which contains the tile processing parameters. ++ * ++ * @edge: Edge tile flag ++ * @pad0: Padding bytes ++ * @input_addr_offset: Top-left pixel offset, in bytes ++ * @input_addr_offset2: Top-left pixel offset, in bytes for the second/ ++ * third image planes ++ * @input_offset_x: Horizontal offset in pixels of this tile in the ++ * input image ++ * @input_offset_y: Vertical offset in pixels of this tile in the ++ * input image ++ * @input_width: Width in pixels of this tile ++ * @input_height: Height in pixels of the this tile ++ * @tdn_input_addr_offset: TDN input image offset, in bytes ++ * @tdn_output_addr_offset: TDN output image offset, in bytes ++ * @stitch_input_addr_offset: Stitch input image offset, in bytes ++ * @stitch_output_addr_offset: Stitch output image offset, in bytes ++ * @lsc_grid_offset_x: Horizontal offset in the LSC table for this tile ++ * @lsc_grid_offset_y: Vertical offset in the LSC table for this tile ++ * @cac_grid_offset_x: Horizontal offset in the CAC table for this tile ++ * @cac_grid_offset_y: Horizontal offset in the CAC table for this tile ++ * @crop_x_start: Number of pixels cropped from the left of the ++ * tile ++ * @crop_x_end: Number of pixels cropped from the right of the ++ * tile ++ * @crop_y_start: Number of pixels cropped from the top of the ++ * tile ++ * @crop_y_end: Number of pixels cropped from the bottom of the ++ * tile ++ * @downscale_phase_x: Initial horizontal phase in pixels ++ * @downscale_phase_y: Initial vertical phase in pixels ++ * @resample_in_width: Width in pixels of the tile entering the ++ * Resample block ++ * @resample_in_height: Height in pixels of the tile entering the ++ * Resample block ++ * @resample_phase_x: Initial horizontal phase for the Resample block ++ * @resample_phase_y: Initial vertical phase for the Resample block ++ * @output_offset_x: Horizontal offset in pixels where the tile will ++ * be written into the output image ++ * @output_offset_y: Vertical offset in pixels where the tile will be ++ * written into the output image ++ * @output_width: Width in pixels in the output image of this tile ++ * @output_height: Height in pixels in the output image of this tile ++ * @output_addr_offset: Offset in bytes into the output buffer ++ * @output_addr_offset2: Offset in bytes into the output buffer for the ++ * second and third plane ++ * @output_hog_addr_offset: Offset in bytes into the HOG buffer where ++ * results of this tile are to be written ++ */ ++struct pisp_tile { ++ __u8 edge; /* enum pisp_tile_edge */ ++ __u8 pad0[3]; ++ /* 4 bytes */ ++ __u32 input_addr_offset; ++ __u32 input_addr_offset2; ++ __u16 input_offset_x; ++ __u16 input_offset_y; ++ __u16 input_width; ++ __u16 input_height; ++ /* 20 bytes */ ++ __u32 tdn_input_addr_offset; ++ __u32 tdn_output_addr_offset; ++ __u32 stitch_input_addr_offset; ++ __u32 stitch_output_addr_offset; ++ /* 36 bytes */ ++ __u32 lsc_grid_offset_x; ++ __u32 lsc_grid_offset_y; ++ /* 44 bytes */ ++ __u32 cac_grid_offset_x; ++ __u32 cac_grid_offset_y; ++ /* 52 bytes */ ++ __u16 crop_x_start[PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 crop_x_end[PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 crop_y_start[PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 crop_y_end[PISP_BACK_END_NUM_OUTPUTS]; ++ /* 68 bytes */ ++ /* Ordering is planes then branches */ ++ __u16 downscale_phase_x[3 * PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 downscale_phase_y[3 * PISP_BACK_END_NUM_OUTPUTS]; ++ /* 92 bytes */ ++ __u16 resample_in_width[PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 resample_in_height[PISP_BACK_END_NUM_OUTPUTS]; ++ /* 100 bytes */ ++ /* Ordering is planes then branches */ ++ __u16 resample_phase_x[3 * PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 resample_phase_y[3 * PISP_BACK_END_NUM_OUTPUTS]; ++ /* 124 bytes */ ++ __u16 output_offset_x[PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 output_offset_y[PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 output_width[PISP_BACK_END_NUM_OUTPUTS]; ++ __u16 output_height[PISP_BACK_END_NUM_OUTPUTS]; ++ /* 140 bytes */ ++ __u32 output_addr_offset[PISP_BACK_END_NUM_OUTPUTS]; ++ __u32 output_addr_offset2[PISP_BACK_END_NUM_OUTPUTS]; ++ /* 156 bytes */ ++ __u32 output_hog_addr_offset; ++ /* 160 bytes */ ++} __attribute__((packed)); ++ ++/** ++ * struct pisp_be_tiles_config - Raspberry Pi PiSP Back End configuration ++ * @tiles: Tile descriptors ++ * @num_tiles: Number of tiles ++ * @config: PiSP Back End configuration ++ */ ++struct pisp_be_tiles_config { ++ struct pisp_tile tiles[PISP_BACK_END_NUM_TILES]; ++ __u32 num_tiles; ++ struct pisp_be_config config; ++} __attribute__((packed)); ++ ++#endif /* _UAPI_PISP_BE_CONFIG_H_ */ +--- /dev/null ++++ b/include/uapi/linux/media/raspberrypi/pisp_common.h +@@ -0,0 +1,199 @@ ++/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ ++/* ++ * RP1 PiSP common definitions. ++ * ++ * Copyright (C) 2021 - Raspberry Pi Ltd. ++ * ++ */ ++#ifndef _UAPI_PISP_COMMON_H_ ++#define _UAPI_PISP_COMMON_H_ ++ ++#include ++ ++struct pisp_image_format_config { ++ /* size in pixels */ ++ __u16 width; ++ __u16 height; ++ /* must match struct pisp_image_format below */ ++ __u32 format; ++ __s32 stride; ++ /* some planar image formats will need a second stride */ ++ __s32 stride2; ++} __attribute__((packed)); ++ ++enum pisp_bayer_order { ++ /* ++ * Note how bayer_order&1 tells you if G is on the even pixels of the ++ * checkerboard or not, and bayer_order&2 tells you if R is on the even ++ * rows or is swapped with B. Note that if the top (of the 8) bits is ++ * set, this denotes a monochrome or greyscale image, and the lower bits ++ * should all be ignored. ++ */ ++ PISP_BAYER_ORDER_RGGB = 0, ++ PISP_BAYER_ORDER_GBRG = 1, ++ PISP_BAYER_ORDER_BGGR = 2, ++ PISP_BAYER_ORDER_GRBG = 3, ++ PISP_BAYER_ORDER_GREYSCALE = 128 ++}; ++ ++enum pisp_image_format { ++ /* ++ * Precise values are mostly tbd. Generally these will be portmanteau ++ * values comprising bit fields and flags. This format must be shared ++ * throughout the PiSP. ++ */ ++ PISP_IMAGE_FORMAT_BPS_8 = 0x00000000, ++ PISP_IMAGE_FORMAT_BPS_10 = 0x00000001, ++ PISP_IMAGE_FORMAT_BPS_12 = 0x00000002, ++ PISP_IMAGE_FORMAT_BPS_16 = 0x00000003, ++ PISP_IMAGE_FORMAT_BPS_MASK = 0x00000003, ++ ++ PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED = 0x00000000, ++ PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR = 0x00000010, ++ PISP_IMAGE_FORMAT_PLANARITY_PLANAR = 0x00000020, ++ PISP_IMAGE_FORMAT_PLANARITY_MASK = 0x00000030, ++ ++ PISP_IMAGE_FORMAT_SAMPLING_444 = 0x00000000, ++ PISP_IMAGE_FORMAT_SAMPLING_422 = 0x00000100, ++ PISP_IMAGE_FORMAT_SAMPLING_420 = 0x00000200, ++ PISP_IMAGE_FORMAT_SAMPLING_MASK = 0x00000300, ++ ++ PISP_IMAGE_FORMAT_ORDER_NORMAL = 0x00000000, ++ PISP_IMAGE_FORMAT_ORDER_SWAPPED = 0x00001000, ++ ++ PISP_IMAGE_FORMAT_SHIFT_0 = 0x00000000, ++ PISP_IMAGE_FORMAT_SHIFT_1 = 0x00010000, ++ PISP_IMAGE_FORMAT_SHIFT_2 = 0x00020000, ++ PISP_IMAGE_FORMAT_SHIFT_3 = 0x00030000, ++ PISP_IMAGE_FORMAT_SHIFT_4 = 0x00040000, ++ PISP_IMAGE_FORMAT_SHIFT_5 = 0x00050000, ++ PISP_IMAGE_FORMAT_SHIFT_6 = 0x00060000, ++ PISP_IMAGE_FORMAT_SHIFT_7 = 0x00070000, ++ PISP_IMAGE_FORMAT_SHIFT_8 = 0x00080000, ++ PISP_IMAGE_FORMAT_SHIFT_MASK = 0x000f0000, ++ ++ PISP_IMAGE_FORMAT_UNCOMPRESSED = 0x00000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_1 = 0x01000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_2 = 0x02000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MODE_3 = 0x03000000, ++ PISP_IMAGE_FORMAT_COMPRESSION_MASK = 0x03000000, ++ ++ PISP_IMAGE_FORMAT_HOG_SIGNED = 0x04000000, ++ PISP_IMAGE_FORMAT_HOG_UNSIGNED = 0x08000000, ++ PISP_IMAGE_FORMAT_INTEGRAL_IMAGE = 0x10000000, ++ PISP_IMAGE_FORMAT_WALLPAPER_ROLL = 0x20000000, ++ PISP_IMAGE_FORMAT_THREE_CHANNEL = 0x40000000, ++ ++ /* Lastly a few specific instantiations of the above. */ ++ PISP_IMAGE_FORMAT_SINGLE_16 = PISP_IMAGE_FORMAT_BPS_16, ++ PISP_IMAGE_FORMAT_THREE_16 = PISP_IMAGE_FORMAT_BPS_16 | ++ PISP_IMAGE_FORMAT_THREE_CHANNEL ++}; ++ ++#define PISP_IMAGE_FORMAT_bps_8(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_8) ++#define PISP_IMAGE_FORMAT_bps_10(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_10) ++#define PISP_IMAGE_FORMAT_bps_12(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_12) ++#define PISP_IMAGE_FORMAT_bps_16(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_16) ++#define PISP_IMAGE_FORMAT_bps(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) ? \ ++ 8 + (2 << (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) - 1)) : 8) ++#define PISP_IMAGE_FORMAT_shift(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_SHIFT_MASK) / PISP_IMAGE_FORMAT_SHIFT_1) ++#define PISP_IMAGE_FORMAT_three_channel(fmt) \ ++ ((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL) ++#define PISP_IMAGE_FORMAT_single_channel(fmt) \ ++ (!((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL)) ++#define PISP_IMAGE_FORMAT_compressed(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_COMPRESSION_MASK) != \ ++ PISP_IMAGE_FORMAT_UNCOMPRESSED) ++#define PISP_IMAGE_FORMAT_sampling_444(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_444) ++#define PISP_IMAGE_FORMAT_sampling_422(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_422) ++#define PISP_IMAGE_FORMAT_sampling_420(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ ++ PISP_IMAGE_FORMAT_SAMPLING_420) ++#define PISP_IMAGE_FORMAT_order_normal(fmt) \ ++ (!((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED)) ++#define PISP_IMAGE_FORMAT_order_swapped(fmt) \ ++ ((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED) ++#define PISP_IMAGE_FORMAT_interleaved(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED) ++#define PISP_IMAGE_FORMAT_semiplanar(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR) ++#define PISP_IMAGE_FORMAT_planar(fmt) \ ++ (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ ++ PISP_IMAGE_FORMAT_PLANARITY_PLANAR) ++#define PISP_IMAGE_FORMAT_wallpaper(fmt) \ ++ ((fmt) & PISP_IMAGE_FORMAT_WALLPAPER_ROLL) ++#define PISP_IMAGE_FORMAT_HOG(fmt) \ ++ ((fmt) & \ ++ (PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED)) ++ ++#define PISP_WALLPAPER_WIDTH 128 /* in bytes */ ++ ++struct pisp_bla_config { ++ __u16 black_level_r; ++ __u16 black_level_gr; ++ __u16 black_level_gb; ++ __u16 black_level_b; ++ __u16 output_black_level; ++ __u8 pad[2]; ++} __attribute__((packed)); ++ ++struct pisp_wbg_config { ++ __u16 gain_r; ++ __u16 gain_g; ++ __u16 gain_b; ++ __u8 pad[2]; ++} __attribute__((packed)); ++ ++struct pisp_compress_config { ++ /* value subtracted from incoming data */ ++ __u16 offset; ++ __u8 pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ __u8 mode; ++} __attribute__((packed)); ++ ++struct pisp_decompress_config { ++ /* value added to reconstructed data */ ++ __u16 offset; ++ __u8 pad; ++ /* 1 => Companding; 2 => Delta (recommended); 3 => Combined (for HDR) */ ++ __u8 mode; ++} __attribute__((packed)); ++ ++enum pisp_axi_flags { ++ /* ++ * round down bursts to end at a 32-byte boundary, to align following ++ * bursts ++ */ ++ PISP_AXI_FLAG_ALIGN = 128, ++ /* for FE writer: force WSTRB high, to pad output to 16-byte boundary */ ++ PISP_AXI_FLAG_PAD = 64, ++ /* for FE writer: Use Output FIFO level to trigger "panic" */ ++ PISP_AXI_FLAG_PANIC = 32, ++}; ++ ++struct pisp_axi_config { ++ /* ++ * burst length minus one, which must be in the range 0:15; OR'd with ++ * flags ++ */ ++ __u8 maxlen_flags; ++ /* { prot[2:0], cache[3:0] } fields, echoed on AXI bus */ ++ __u8 cache_prot; ++ /* QoS field(s) (4x4 bits for FE writer; 4 bits for other masters) */ ++ __u16 qos; ++} __attribute__((packed)); ++ ++#endif /* _UAPI_PISP_COMMON_H_ */ diff --git a/target/linux/bcm27xx/patches-6.6/950-1150-media-uapi-Document-meta-pixel-format-for-PiSP-BE-co.patch b/target/linux/bcm27xx/patches-6.6/950-1150-media-uapi-Document-meta-pixel-format-for-PiSP-BE-co.patch new file mode 100644 index 0000000000..0ee62a7d33 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1150-media-uapi-Document-meta-pixel-format-for-PiSP-BE-co.patch @@ -0,0 +1,86 @@ +From 7ca73020a5b26599d539083e413784e79891107e Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 26 Jan 2024 15:04:59 +0100 +Subject: [PATCH 1150/1215] media: uapi: Document meta pixel format for PiSP BE + config + +Add format description for the PiSP Back End configuration parameter +buffer. + +Signed-off-by: Jacopo Mondi +Reviewed-by: Naushir Patuck +--- + .../userspace-api/media/v4l/meta-formats.rst | 1 + + .../media/v4l/metafmt-pisp-be.rst | 56 +++++++++++++++++++ + 2 files changed, 57 insertions(+) + create mode 100644 Documentation/userspace-api/media/v4l/metafmt-pisp-be.rst + +--- a/Documentation/userspace-api/media/v4l/meta-formats.rst ++++ b/Documentation/userspace-api/media/v4l/meta-formats.rst +@@ -15,6 +15,7 @@ These formats are used for the :ref:`met + metafmt-bcm2835-isp-stats + metafmt-d4xx + metafmt-intel-ipu3 ++ metafmt-pisp-be + metafmt-rkisp1 + metafmt-sensor-data + metafmt-uvc +--- /dev/null ++++ b/Documentation/userspace-api/media/v4l/metafmt-pisp-be.rst +@@ -0,0 +1,56 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++.. _v4l2-meta-fmt-rpi-be-cfg: ++ ++************************ ++V4L2_META_FMT_RPI_BE_CFG ++************************ ++ ++Raspberry Pi PiSP Back End configuration format ++=============================================== ++ ++The Raspberry Pi PiSP Back End memory-to-memory image signal processor is ++configured by userspace by providing a buffer of configuration parameters ++to the `pispbe-config` output video device node using the ++:c:type:`v4l2_meta_format` interface. ++ ++The PiSP Back End processes images in tiles, and its configuration requires ++specifying two different sets of parameters by populating the members of ++:c:type:`pisp_be_tiles_config` defined in the ``pisp_be_config.h`` header file. ++ ++The `Raspberry Pi PiSP technical specification ++`_ ++provide detailed description of the ISP back end configuration and programming ++model. ++ ++Global configuration data ++------------------------- ++ ++The global configuration data describe how the pixels in a particular image are ++to be processed and is therefore shared across all the tiles of the image. So ++for example, LSC (Lens Shading Correction) or Denoise parameters would be common ++across all tiles from the same frame. ++ ++Global configuration data are passed to the ISP by populating the member of ++:c:type:`pisp_be_config`. ++ ++Tile parameters ++--------------- ++ ++As the ISP processes images in tiles, each set of tiles parameters describe how ++a single tile in an image is going to be processed. A single set of tile ++parameters consist of 160 bytes of data and to process a batch of tiles several ++sets of tiles parameters are required. ++ ++Tiles parameters are passed to the ISP by populating the member of ++``pisp_tile`` and the ``num_tiles`` fields of :c:type:`pisp_be_tiles_config`. ++ ++Raspberry Pi PiSP Back End uAPI data types ++========================================== ++ ++This section describes the data types exposed to userspace by the Raspberry Pi ++PiSP Back End. The section is informative only, for a detailed description of ++each field refer to the `Raspberry Pi PiSP technical specification ++`_. ++ ++.. kernel-doc:: include/uapi/linux/media/raspberrypi/pisp_be_config.h diff --git a/target/linux/bcm27xx/patches-6.6/950-1151-media-uapi-Document-PiSP-Compressed-RAW-Bayer-format.patch b/target/linux/bcm27xx/patches-6.6/950-1151-media-uapi-Document-PiSP-Compressed-RAW-Bayer-format.patch new file mode 100644 index 0000000000..aa4b003e5b --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1151-media-uapi-Document-PiSP-Compressed-RAW-Bayer-format.patch @@ -0,0 +1,106 @@ +From 5d6318f242cce5f9b5677baedde736a2b81061df Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Wed, 17 Jan 2024 11:21:50 +0200 +Subject: [PATCH 1151/1215] media: uapi: Document PiSP Compressed RAW Bayer + formats + +Document the Raspberry Pi compressed RAW Bayer formats. + +The compression algorithm description is provided by Nick Hollinghurst + from Raspberry Pi. + +Signed-off-by: Jacopo Mondi +Reviewed-by: Naushir Patuck +--- + .../userspace-api/media/v4l/pixfmt-bayer.rst | 1 + + .../media/v4l/pixfmt-srggb8-pisp-comp.rst | 74 +++++++++++++++++++ + 2 files changed, 75 insertions(+) + create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-srggb8-pisp-comp.rst + +--- a/Documentation/userspace-api/media/v4l/pixfmt-bayer.rst ++++ b/Documentation/userspace-api/media/v4l/pixfmt-bayer.rst +@@ -20,6 +20,7 @@ orders. See also `the Wikipedia article + :maxdepth: 1 + + pixfmt-srggb8 ++ pixfmt-srggb8-pisp-comp + pixfmt-srggb10 + pixfmt-srggb10p + pixfmt-srggb10alaw8 +--- /dev/null ++++ b/Documentation/userspace-api/media/v4l/pixfmt-srggb8-pisp-comp.rst +@@ -0,0 +1,74 @@ ++.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later ++ ++.. _v4l2-pix-fmt-pisp-comp1-rggb: ++.. _v4l2-pix-fmt-pisp-comp1-grbg: ++.. _v4l2-pix-fmt-pisp-comp1-gbrg: ++.. _v4l2-pix-fmt-pisp-comp1-bggr: ++.. _v4l2-pix-fmt-pisp-comp1-mono: ++.. _v4l2-pix-fmt-pisp-comp2-rggb: ++.. _v4l2-pix-fmt-pisp-comp2-grbg: ++.. _v4l2-pix-fmt-pisp-comp2-gbrg: ++.. _v4l2-pix-fmt-pisp-comp2-bggr: ++.. _v4l2-pix-fmt-pisp-comp2-mono: ++ ++************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** ++V4L2_PIX_FMT_PISP_COMP1_RGGB ('PC1R'), V4L2_PIX_FMT_PISP_COMP1_GRBG ('PC1G'), V4L2_PIX_FMT_PISP_COMP1_GBRG ('PC1g'), V4L2_PIX_FMT_PISP_COMP1_BGGR ('PC1B), V4L2_PIX_FMT_PISP_COMP1_MONO ('PC1M'), V4L2_PIX_FMT_PISP_COMP2_RGGB ('PC2R'), V4L2_PIX_FMT_PISP_COMP2_GRBG ('PC2G'), V4L2_PIX_FMT_PISP_COMP2_GBRG ('PC2g'), V4L2_PIX_FMT_PISP_COMP2_BGGR ('PC2B), V4L2_PIX_FMT_PISP_COMP2_MONO ('PC2M') ++************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** ++ ++================================================ ++Raspberry Pi PiSP compressed 8-bit Bayer formats ++================================================ ++ ++Description ++=========== ++ ++The Raspberry Pi ISP (PiSP) uses a family of three fixed-rate compressed Bayer ++formats. A black-level offset may be subtracted to improve compression ++efficiency; the nominal black level and amount of offset must be signalled out ++of band. Each scanline is padded to a multiple of 8 pixels wide, and each block ++of 8 horizontally-contiguous pixels is coded using 8 bytes. ++ ++Mode 1 uses a quantization and delta-based coding scheme which preserves up to ++12 significant bits. Mode 2 is a simple sqrt-like companding scheme with 6 PWL ++chords, preserving up to 12 significant bits. Mode 3 combines both companding ++(with 4 chords) and the delta scheme, preserving up to 14 significant bits. ++ ++The remainder of this description applies to Modes 1 and 3. ++ ++Each block of 8 pixels is separated into even and odd phases of 4 pixels, ++coded independently by 32-bit words at successive locations in memory. ++The two LS bits of each 32-bit word give its "quantization mode". ++ ++In quantization mode 0, the lowest 321 quantization levels are multiples of ++FSD/4096 and the remaining levels are successive multiples of FSD/2048. ++Quantization modes 1 and 2 use linear quantization with step sizes of ++FSD/1024 and FSD/512 respectively. Each of the four pixels is quantized ++independently, with rounding to the nearest level. ++In quantization mode 2 where the middle two samples have quantized values ++(q1,q2) both in the range [384..511], they are coded using 9 bits for q1 ++followed by 7 bits for (q2 & 127). Otherwise, for quantization modes ++0, 1 and 2: a 9-bit field encodes MIN(q1,q2) which must be in the range ++[0..511] and a 7-bit field encodes (q2-q1+64) which must be in [0..127]. ++ ++Each of the outer samples (q0,q3) is encoded using a 7-bit field based ++on its inner neighbour q1 or q2. In quantization mode 2 where the inner ++sample has a quantized value in the range [448..511], the field value is ++(q0-384). Otherwise for quantization modes 0, 1 and 2: The outer sample ++is encoded as (q0-MAX(0,q1-64)). q3 is likewise coded based on q2. ++Each of these values must be in the range [0..127]. All these fields ++of 2, 9, 7, 7, 7 bits respectively are packed in little-endian order ++to give a 32-bit word with LE byte order. ++ ++Quantization mode 3 has a "7.5-bit" escape, used when none of the above ++encodings will fit. Each pixel value is quantized to the nearest of 176 ++levels, where the lowest 95 levels are multiples of FSD/256 and the ++remaining levels are multiples of FSD/128 (level 175 represents values ++very close to FSD and may require saturating arithmetic to decode). ++ ++Each pair of quantized pixels (q0,q1) or (q2,q3) is jointly coded ++by a 15-bit field: 2816*(q0>>4) + 16*q1 + (q0&15). ++Three fields of 2, 15, 15 bits are packed in LE order {15,15,2}. ++ ++An implementation of a software decoder of compressed formats is available ++in `Raspberry Pi camera applications code base ++`_. diff --git a/target/linux/bcm27xx/patches-6.6/950-1152-media-dt-bindings-Add-bindings-for-Raspberry-Pi-PiSP.patch b/target/linux/bcm27xx/patches-6.6/950-1152-media-dt-bindings-Add-bindings-for-Raspberry-Pi-PiSP.patch new file mode 100644 index 0000000000..30c5cb3506 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1152-media-dt-bindings-Add-bindings-for-Raspberry-Pi-PiSP.patch @@ -0,0 +1,97 @@ +From c38a898c6877c6722ebfecea99f42e5a84c3e453 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Thu, 25 Jan 2024 16:42:33 +0100 +Subject: [PATCH 1152/1215] media: dt-bindings: Add bindings for Raspberry Pi + PiSP Back End + +Add bindings for the Raspberry Pi PiSP Back End memory-to-memory image +signal processor. + +Datasheet: +https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf + +Signed-off-by: Jacopo Mondi +Reviewed-by: Rob Herring +Reviewed-by: Naushir Patuck +--- + .../bindings/media/raspberrypi,pispbe.yaml | 63 +++++++++++++++++++ + MAINTAINERS | 1 + + 2 files changed, 64 insertions(+) + create mode 100644 Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml +@@ -0,0 +1,63 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/media/raspberrypi,pispbe.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Raspberry Pi PiSP Image Signal Processor (ISP) Back End ++ ++maintainers: ++ - Raspberry Pi Kernel Maintenance ++ - Jacopo Mondi ++ ++description: | ++ The Raspberry Pi PiSP Image Signal Processor (ISP) Back End is an image ++ processor that fetches images in Bayer or Grayscale format from DRAM memory ++ in tiles and produces images consumable by applications. ++ ++ The full ISP documentation is available at ++ https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf ++ ++properties: ++ compatible: ++ items: ++ - enum: ++ - brcm,bcm2712-pispbe ++ - const: raspberrypi,pispbe ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ maxItems: 1 ++ ++ iommus: ++ maxItems: 1 ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ isp@880000 { ++ compatible = "brcm,bcm2712-pispbe", "raspberrypi,pispbe"; ++ reg = <0x10 0x00880000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&firmware_clocks 7>; ++ iommus = <&iommu2>; ++ }; ++ }; +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -18037,6 +18037,7 @@ M: Jacopo Mondi + L: linux-media@vger.kernel.org + S: Maintained ++F: Documentation/devicetree/bindings/media/raspberrypi,pispbe.yaml + F: include/uapi/linux/media/raspberrypi/ + + RC-CORE / LIRC FRAMEWORK diff --git a/target/linux/bcm27xx/patches-6.6/950-1153-media-admin-guide-Document-the-Raspberry-Pi-PiSP-BE.patch b/target/linux/bcm27xx/patches-6.6/950-1153-media-admin-guide-Document-the-Raspberry-Pi-PiSP-BE.patch new file mode 100644 index 0000000000..f443cc78c7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1153-media-admin-guide-Document-the-Raspberry-Pi-PiSP-BE.patch @@ -0,0 +1,162 @@ +From d68e76260316002869aea1b0edf4be399bb592b8 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Mon, 29 Jan 2024 17:23:55 +0100 +Subject: [PATCH 1153/1215] media: admin-guide: Document the Raspberry Pi PiSP + BE + +Add documentation for the PiSP Back End memory-to-memory ISP. + +Signed-off-by: Jacopo Mondi +--- + .../admin-guide/media/raspberrypi-pisp-be.dot | 20 ++++ + .../admin-guide/media/raspberrypi-pisp-be.rst | 109 ++++++++++++++++++ + .../admin-guide/media/v4l-drivers.rst | 1 + + 3 files changed, 130 insertions(+) + create mode 100644 Documentation/admin-guide/media/raspberrypi-pisp-be.dot + create mode 100644 Documentation/admin-guide/media/raspberrypi-pisp-be.rst + +--- /dev/null ++++ b/Documentation/admin-guide/media/raspberrypi-pisp-be.dot +@@ -0,0 +1,20 @@ ++digraph board { ++ rankdir=TB ++ n00000001 [label="{{ 0 | 1 | 2 | 7} | pispbe\n | { 3 | 4 | 5 | 6}}", shape=Mrecord, style=filled, fillcolor=green] ++ n00000001:port3 -> n0000001c [style=bold] ++ n00000001:port4 -> n00000022 [style=bold] ++ n00000001:port5 -> n00000028 [style=bold] ++ n00000001:port6 -> n0000002e [style=bold] ++ n0000000a [label="pispbe-input\n/dev/video0", shape=box, style=filled, fillcolor=yellow] ++ n0000000a -> n00000001:port0 [style=bold] ++ n00000010 [label="pispbe-tdn_input\n/dev/video1", shape=box, style=filled, fillcolor=yellow] ++ n00000010 -> n00000001:port1 [style=bold] ++ n00000016 [label="pispbe-stitch_input\n/dev/video2", shape=box, style=filled, fillcolor=yellow] ++ n00000016 -> n00000001:port2 [style=bold] ++ n0000001c [label="pispbe-output0\n/dev/video3", shape=box, style=filled, fillcolor=yellow] ++ n00000022 [label="pispbe-output1\n/dev/video4", shape=box, style=filled, fillcolor=yellow] ++ n00000028 [label="pispbe-tdn_output\n/dev/video5", shape=box, style=filled, fillcolor=yellow] ++ n0000002e [label="pispbe-stitch_output\n/dev/video6", shape=box, style=filled, fillcolor=yellow] ++ n00000034 [label="pispbe-config\n/dev/video7", shape=box, style=filled, fillcolor=yellow] ++ n00000034 -> n00000001:port7 [style=bold] ++} +--- /dev/null ++++ b/Documentation/admin-guide/media/raspberrypi-pisp-be.rst +@@ -0,0 +1,109 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++========================================================= ++Raspberry Pi PiSP Back End Memory-to-Memory ISP (pisp-be) ++========================================================= ++ ++The PiSP Back End ++================= ++ ++The PiSP Back End is a memory-to-memory Image Signal Processor (ISP) which reads ++image data from DRAM memory and performs image processing as specified by the ++application through the parameters in a configuration buffer, before writing ++pixel data back to memory through two distinct output channels. ++ ++The ISP registers and programming model are documented in the `Raspberry Pi ++Image Signal Processor (PiSP) Specification document`_ ++ ++The PiSP Back End ISP processes images in tiles. The handling of image ++tessellation and the computation of low-level configuration parameters is ++realized by a free software library called `libpisp ++`_. ++ ++The full image processing pipeline, which involves capturing RAW Bayer data from ++an image sensor through a MIPI CSI-2 compatible capture interface, storing them ++in DRAM memory and processing them in the PiSP Back End to obtain images usable ++by an application is implemented in `libcamera `_ as ++part of the Raspberry Pi platform support. ++ ++The pisp-be driver ++================== ++ ++The Raspberry Pi PiSP Back End (pisp-be) driver is located under ++drivers/media/platform/raspberrypi/pisp-be. It uses the `V4L2 API` to register ++a number of video capture and output devices, the `V4L2 subdev API` to register ++a subdevice for the ISP that connects the video devices in a single media graph ++realized using the `Media Controller (MC) API`. ++ ++The media topology registered by the `pisp-be` driver is represented below: ++ ++.. _pips-be-topology: ++ ++.. kernel-figure:: raspberrypi-pisp-be.dot ++ :alt: Diagram of the default media pipeline topology ++ :align: center ++ ++ ++The media graph registers the following video device nodes: ++ ++- pispbe-input: output device for images to be submitted to the ISP for ++ processing. ++- pispbe-tdn_input: output device for temporal denoise. ++- pispbe-stitch_input: output device for image stitching (HDR). ++- pispbe-output0: first capture device for processed images. ++- pispbe-output1: second capture device for processed images. ++- pispbe-tdn_output: capture device for temporal denoise. ++- pispbe-stitch_output: capture device for image stitching (HDR). ++- pispbe-config: output device for ISP configuration parameters. ++ ++pispbe-input ++------------ ++ ++Images to be processed by the ISP are queued to the `pispbe-input` output device ++node. For a list of image formats supported as input to the ISP refer to the ++`Raspberry Pi Image Signal Processor (PiSP) Specification document`_. ++ ++pispbe-tdn_input, pispbe-tdn_output ++----------------------------------- ++ ++The `pispbe-tdn_input` output video device receives images to be processed by ++the temporal denoise block which are captured from the `pispbe-tdn_output` ++capture video device. Userspace is responsible for maintaining queues on both ++devices, and ensuring that buffers completed on the output are queued to the ++input. ++ ++pispbe-stitch_input, pispbe-stitch_output ++----------------------------------------- ++ ++To realize HDR (high dynamic range) image processing the image stitching and ++tonemapping blocks are used. The `pispbe-stitch_output` writes images to memory ++and the `pispbe-stitch_input` receives the previously written frame to process ++it along with the current input image. Userspace is responsible for maintaining ++queues on both devices, and ensuring that buffers completed on the output are ++queued to the input. ++ ++pispbe-output0, pispbe-output1 ++------------------------------ ++ ++The two capture devices write to memory the pixel data as processed by the ISP. ++ ++pispbe-config ++------------- ++ ++The `pispbe-config` output video devices receives a buffer of configuration ++parameters that define the desired image processing to be performed by the ISP. ++ ++The format of the ISP configuration parameter is defined by ++:c:type:`pisp_be_tiles_config` C structure and the meaning of each parameter is ++described in the `Raspberry Pi Image Signal Processor (PiSP) Specification ++document`_. ++ ++ISP configuration ++================= ++ ++The ISP configuration is described solely by the content of the parameters ++buffer. The only parameter that userspace needs to configure using the V4L2 API ++is the image format on the output and capture video devices for validation of ++the content of the parameters buffer. ++ ++.. _Raspberry Pi Image Signal Processor (PiSP) Specification document: https://datasheets.raspberrypi.com/camera/raspberry-pi-image-signal-processor-specification.pdf +--- a/Documentation/admin-guide/media/v4l-drivers.rst ++++ b/Documentation/admin-guide/media/v4l-drivers.rst +@@ -21,6 +21,7 @@ Video4Linux (V4L) driver-specific docume + omap4_camera + philips + qcom_camss ++ raspberrypi-pisp-be + rcar-fdp1 + rkisp1 + saa7134 diff --git a/target/linux/bcm27xx/patches-6.6/950-1154-media-pisp-be-Backport-the-mainline-PiSP-BE-driver.patch b/target/linux/bcm27xx/patches-6.6/950-1154-media-pisp-be-Backport-the-mainline-PiSP-BE-driver.patch new file mode 100644 index 0000000000..a0123995fe --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1154-media-pisp-be-Backport-the-mainline-PiSP-BE-driver.patch @@ -0,0 +1,2927 @@ +From c75989589bf77530f4013e0bc799169504c69937 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Thu, 27 Jun 2024 11:41:22 +0200 +Subject: [PATCH 1154/1215] media: pisp-be: Backport the mainline PiSP BE + driver + +Backport to rpi-6.6.y the mainline version of the PiSP BE driver. + +The backported version of the driver corresponds to the one available +at: +https://lore.kernel.org/all/20240626181440.195137-1-jacopo.mondi@ideasonboard.com/ + +Signed-off-by: Jacopo Mondi +--- + .../platform/raspberrypi/pisp_be/Kconfig | 4 +- + .../platform/raspberrypi/pisp_be/pisp_be.c | 1288 +++++++---------- + .../raspberrypi/pisp_be/pisp_be_config.h | 533 ------- + .../raspberrypi/pisp_be/pisp_be_formats.h | 44 +- + 4 files changed, 572 insertions(+), 1297 deletions(-) + delete mode 100644 drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h + +--- a/drivers/media/platform/raspberrypi/pisp_be/Kconfig ++++ b/drivers/media/platform/raspberrypi/pisp_be/Kconfig +@@ -1,10 +1,10 @@ + config VIDEO_RASPBERRYPI_PISP_BE + tristate "Raspberry Pi PiSP Backend (BE) ISP driver" +- depends on VIDEO_DEV && PM ++ depends on V4L_PLATFORM_DRIVERS ++ depends on VIDEO_DEV + select VIDEO_V4L2_SUBDEV_API + select MEDIA_CONTROLLER + select VIDEOBUF2_DMA_CONTIG +- select V4L2_FWNODE + help + Say Y here to enable support for the PiSP Backend (BE) ISP driver. + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +@@ -1,12 +1,14 @@ + // SPDX-License-Identifier: GPL-2.0 + /* + * PiSP Back End driver. +- * Copyright (c) 2021-2022 Raspberry Pi Limited. ++ * Copyright (c) 2021-2024 Raspberry Pi Limited. + * + */ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -15,49 +17,39 @@ + #include + #include + +-#include "pisp_be_config.h" +-#include "pisp_be_formats.h" +- +-MODULE_DESCRIPTION("PiSP Back End driver"); +-MODULE_AUTHOR("David Plowman "); +-MODULE_AUTHOR("Nick Hollinghurst "); +-MODULE_LICENSE("GPL v2"); ++#include + +-/* Offset to use when registering the /dev/videoX node */ +-#define PISPBE_VIDEO_NODE_OFFSET 20 ++#include "pisp_be_formats.h" + + /* Maximum number of config buffers possible */ + #define PISP_BE_NUM_CONFIG_BUFFERS VB2_MAX_FRAME + +-/* +- * We want to support 2 independent instances allowing 2 simultaneous users +- * of the ISP-BE (of course they share hardware, platform resources and mutex). +- * Each such instance comprises a group of device nodes representing input +- * and output queues, and a media controller device node to describe them. +- */ +-#define PISPBE_NUM_NODE_GROUPS 2 +- + #define PISPBE_NAME "pispbe" + + /* Some ISP-BE registers */ +-#define PISP_BE_VERSION_OFFSET (0x0) +-#define PISP_BE_CONTROL_OFFSET (0x4) +-#define PISP_BE_TILE_ADDR_LO_OFFSET (0x8) +-#define PISP_BE_TILE_ADDR_HI_OFFSET (0xc) +-#define PISP_BE_STATUS_OFFSET (0x10) +-#define PISP_BE_BATCH_STATUS_OFFSET (0x14) +-#define PISP_BE_INTERRUPT_EN_OFFSET (0x18) +-#define PISP_BE_INTERRUPT_STATUS_OFFSET (0x1c) +-#define PISP_BE_AXI_OFFSET (0x20) +-#define PISP_BE_CONFIG_BASE_OFFSET (0x40) +-#define PISP_BE_IO_INPUT_ADDR0_LO_OFFSET (PISP_BE_CONFIG_BASE_OFFSET) +-#define PISP_BE_GLOBAL_BAYER_ENABLE_OFFSET (PISP_BE_CONFIG_BASE_OFFSET + 0x70) +-#define PISP_BE_GLOBAL_RGB_ENABLE_OFFSET (PISP_BE_CONFIG_BASE_OFFSET + 0x74) +-#define N_HW_ADDRESSES 14 +-#define N_HW_ENABLES 2 ++#define PISP_BE_VERSION_REG 0x0 ++#define PISP_BE_CONTROL_REG 0x4 ++#define PISP_BE_CONTROL_COPY_CONFIG BIT(1) ++#define PISP_BE_CONTROL_QUEUE_JOB BIT(0) ++#define PISP_BE_CONTROL_NUM_TILES(n) ((n) << 16) ++#define PISP_BE_TILE_ADDR_LO_REG 0x8 ++#define PISP_BE_TILE_ADDR_HI_REG 0xc ++#define PISP_BE_STATUS_REG 0x10 ++#define PISP_BE_STATUS_QUEUED BIT(0) ++#define PISP_BE_BATCH_STATUS_REG 0x14 ++#define PISP_BE_INTERRUPT_EN_REG 0x18 ++#define PISP_BE_INTERRUPT_STATUS_REG 0x1c ++#define PISP_BE_AXI_REG 0x20 ++#define PISP_BE_CONFIG_BASE_REG 0x40 ++#define PISP_BE_IO_ADDR_LOW(n) (PISP_BE_CONFIG_BASE_REG + 8 * (n)) ++#define PISP_BE_IO_ADDR_HIGH(n) (PISP_BE_IO_ADDR_LOW((n)) + 4) ++#define PISP_BE_GLOBAL_BAYER_ENABLE 0xb0 ++#define PISP_BE_GLOBAL_RGB_ENABLE 0xb4 ++#define N_HW_ADDRESSES 13 ++#define N_HW_ENABLES 2 + +-#define PISP_BE_VERSION_2712C1 0x02252700 +-#define PISP_BE_VERSION_MINOR_BITS 0xF ++#define PISP_BE_VERSION_2712 0x02252700 ++#define PISP_BE_VERSION_MINOR_BITS 0xf + + /* + * This maps our nodes onto the inputs/outputs of the actual PiSP Back End. +@@ -65,11 +57,10 @@ MODULE_LICENSE("GPL v2"); + * context it means an input to the hardware (source image or metadata). + * Elsewhere it means an output from the hardware. + */ +-enum node_ids { ++enum pispbe_node_ids { + MAIN_INPUT_NODE, + TDN_INPUT_NODE, + STITCH_INPUT_NODE, +- HOG_OUTPUT_NODE, + OUTPUT0_NODE, + OUTPUT1_NODE, + TDN_OUTPUT_NODE, +@@ -78,13 +69,13 @@ enum node_ids { + PISPBE_NUM_NODES + }; + +-struct node_description { ++struct pispbe_node_description { + const char *ent_name; + enum v4l2_buf_type buf_type; + unsigned int caps; + }; + +-static const struct node_description node_desc[PISPBE_NUM_NODES] = { ++static const struct pispbe_node_description node_desc[PISPBE_NUM_NODES] = { + /* MAIN_INPUT_NODE */ + { + .ent_name = PISPBE_NAME "-input", +@@ -103,12 +94,6 @@ static const struct node_description nod + .buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .caps = V4L2_CAP_VIDEO_OUTPUT_MPLANE, + }, +- /* HOG_OUTPUT_NODE */ +- { +- .ent_name = PISPBE_NAME "-hog_output", +- .buf_type = V4L2_BUF_TYPE_META_CAPTURE, +- .caps = V4L2_CAP_META_CAPTURE, +- }, + /* OUTPUT0_NODE */ + { + .ent_name = PISPBE_NAME "-output0", +@@ -147,14 +132,12 @@ static const struct node_description nod + ((desc)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) + + #define NODE_IS_META(node) ( \ +- ((node)->buf_type == V4L2_BUF_TYPE_META_OUTPUT) || \ +- ((node)->buf_type == V4L2_BUF_TYPE_META_CAPTURE)) ++ ((node)->buf_type == V4L2_BUF_TYPE_META_OUTPUT)) + #define NODE_IS_OUTPUT(node) ( \ + ((node)->buf_type == V4L2_BUF_TYPE_META_OUTPUT) || \ + ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT) || \ + ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) + #define NODE_IS_CAPTURE(node) ( \ +- ((node)->buf_type == V4L2_BUF_TYPE_META_CAPTURE) || \ + ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) || \ + ((node)->buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) + #define NODE_IS_MPLANE(node) ( \ +@@ -173,9 +156,12 @@ struct pispbe_node { + struct media_pad pad; + struct media_intf_devnode *intf_devnode; + struct media_link *intf_link; +- struct pispbe_node_group *node_group; ++ struct pispbe_dev *pispbe; ++ /* Video device lock */ + struct mutex node_lock; ++ /* vb2_queue lock */ + struct mutex queue_lock; ++ /* Protect pispbe_node->ready_queue and pispbe_buffer->ready_list */ + spinlock_t ready_lock; + struct list_head ready_queue; + struct vb2_queue queue; +@@ -186,29 +172,10 @@ struct pispbe_node { + /* For logging only, use the entity name with "pispbe" and separator removed */ + #define NODE_NAME(node) \ + (node_desc[(node)->id].ent_name + sizeof(PISPBE_NAME)) +-#define NODE_GET_V4L2(node) ((node)->node_group->v4l2_dev) +- +-/* +- * Node group structure, which comprises all the input and output nodes that a +- * single PiSP client will need, along with its own v4l2 and media devices. +- */ +-struct pispbe_node_group { +- unsigned int id; +- struct v4l2_device v4l2_dev; +- struct v4l2_subdev sd; +- struct pispbe_dev *pispbe; +- struct media_device mdev; +- struct pispbe_node node[PISPBE_NUM_NODES]; +- u32 streaming_map; /* bitmap of which nodes are streaming */ +- struct media_pad pad[PISPBE_NUM_NODES]; /* output pads first */ +- struct pisp_be_tiles_config *config; +- dma_addr_t config_dma_addr; +- unsigned int sequence; +-}; + + /* Records details of the jobs currently running or queued on the h/w. */ + struct pispbe_job { +- struct pispbe_node_group *node_group; ++ bool valid; + /* + * An array of buffer pointers - remember it's source buffers first, + * then captures, then metadata last. +@@ -216,85 +183,66 @@ struct pispbe_job { + struct pispbe_buffer *buf[PISPBE_NUM_NODES]; + }; + ++struct pispbe_hw_enables { ++ u32 bayer_enables; ++ u32 rgb_enables; ++}; ++ ++/* Records a job configuration and memory addresses. */ ++struct pispbe_job_descriptor { ++ dma_addr_t hw_dma_addrs[N_HW_ADDRESSES]; ++ struct pisp_be_tiles_config *config; ++ struct pispbe_hw_enables hw_enables; ++ dma_addr_t tiles; ++}; ++ + /* + * Structure representing the entire PiSP Back End device, comprising several +- * node groups which share platform resources and a mutex for the actual HW. ++ * nodes which share platform resources and a mutex for the actual HW. + */ + struct pispbe_dev { + struct device *dev; +- struct pispbe_node_group node_group[PISPBE_NUM_NODE_GROUPS]; +- int hw_busy; /* non-zero if a job is queued or is being started */ +- struct pispbe_job queued_job, running_job; ++ struct pispbe_dev *pispbe; ++ struct pisp_be_tiles_config *config; + void __iomem *be_reg_base; + struct clk *clk; ++ struct v4l2_device v4l2_dev; ++ struct v4l2_subdev sd; ++ struct media_device mdev; ++ struct media_pad pad[PISPBE_NUM_NODES]; /* output pads first */ ++ struct pispbe_node node[PISPBE_NUM_NODES]; ++ dma_addr_t config_dma_addr; ++ unsigned int sequence; ++ u32 streaming_map; ++ struct pispbe_job queued_job, running_job; ++ spinlock_t hw_lock; /* protects "hw_busy" flag and streaming_map */ ++ bool hw_busy; /* non-zero if a job is queued or is being started */ + int irq; + u32 hw_version; + u8 done, started; +- spinlock_t hw_lock; /* protects "hw_busy" flag and streaming_map */ + }; + +-static inline u32 read_reg(struct pispbe_dev *pispbe, unsigned int offset) ++static u32 pispbe_rd(struct pispbe_dev *pispbe, unsigned int offset) + { + return readl(pispbe->be_reg_base + offset); + } + +-static inline void write_reg(struct pispbe_dev *pispbe, unsigned int offset, +- u32 val) ++static void pispbe_wr(struct pispbe_dev *pispbe, unsigned int offset, u32 val) + { + writel(val, pispbe->be_reg_base + offset); + } + +-/* Check and initialize hardware. */ +-static int hw_init(struct pispbe_dev *pispbe) +-{ +- u32 u; +- +- /* Check the HW is present and has a known version */ +- u = read_reg(pispbe, PISP_BE_VERSION_OFFSET); +- dev_info(pispbe->dev, "pispbe_probe: HW version: 0x%08x", u); +- pispbe->hw_version = u; +- if ((u & ~PISP_BE_VERSION_MINOR_BITS) != PISP_BE_VERSION_2712C1) +- return -ENODEV; +- +- /* Clear leftover interrupts */ +- write_reg(pispbe, PISP_BE_INTERRUPT_STATUS_OFFSET, 0xFFFFFFFFu); +- u = read_reg(pispbe, PISP_BE_BATCH_STATUS_OFFSET); +- dev_info(pispbe->dev, "pispbe_probe: BatchStatus: 0x%08x", u); +- pispbe->done = (uint8_t)u; +- pispbe->started = (uint8_t)(u >> 8); +- u = read_reg(pispbe, PISP_BE_STATUS_OFFSET); +- dev_info(pispbe->dev, "pispbe_probe: Status: 0x%08x", u); +- if (u != 0 || pispbe->done != pispbe->started) { +- dev_err(pispbe->dev, "pispbe_probe: HW is stuck or busy\n"); +- return -EBUSY; +- } +- /* +- * AXI QOS=0, CACHE=4'b0010, PROT=3'b011 +- * Also set "chicken bits" 22:20 which enable sub-64-byte bursts +- * and AXI AWID/BID variability (on versions which support this). +- */ +- write_reg(pispbe, PISP_BE_AXI_OFFSET, 0x32703200u); +- +- /* Enable both interrupt flags */ +- write_reg(pispbe, PISP_BE_INTERRUPT_EN_OFFSET, 0x00000003u); +- return 0; +-} +- + /* + * Queue a job to the h/w. If the h/w is idle it will begin immediately. + * Caller must ensure it is "safe to queue", i.e. we don't already have a + * queued, unstarted job. + */ +-static void hw_queue_job(struct pispbe_dev *pispbe, +- dma_addr_t hw_dma_addrs[N_HW_ADDRESSES], +- u32 hw_enables[N_HW_ENABLES], +- struct pisp_be_config *config, dma_addr_t tiles, +- unsigned int num_tiles) ++static void pispbe_queue_job(struct pispbe_dev *pispbe, ++ struct pispbe_job_descriptor *job) + { + unsigned int begin, end; +- unsigned int u; + +- if (read_reg(pispbe, PISP_BE_STATUS_OFFSET) & 1) ++ if (pispbe_rd(pispbe, PISP_BE_STATUS_REG) & PISP_BE_STATUS_QUEUED) + dev_err(pispbe->dev, "ERROR: not safe to queue new job!\n"); + + /* +@@ -303,51 +251,49 @@ static void hw_queue_job(struct pispbe_d + * and we don't want to modify (or be vulnerable to modifications of) + * the mmap'd buffer. + */ +- for (u = 0; u < N_HW_ADDRESSES; ++u) { +- write_reg(pispbe, PISP_BE_IO_INPUT_ADDR0_LO_OFFSET + 8 * u, +- (u32)(hw_dma_addrs[u])); +- write_reg(pispbe, PISP_BE_IO_INPUT_ADDR0_LO_OFFSET + 8 * u + 4, +- (u32)(hw_dma_addrs[u] >> 32)); +- } +- write_reg(pispbe, PISP_BE_GLOBAL_BAYER_ENABLE_OFFSET, hw_enables[0]); +- write_reg(pispbe, PISP_BE_GLOBAL_RGB_ENABLE_OFFSET, hw_enables[1]); ++ for (unsigned int u = 0; u < N_HW_ADDRESSES; ++u) { ++ pispbe_wr(pispbe, PISP_BE_IO_ADDR_LOW(u), ++ lower_32_bits(job->hw_dma_addrs[u])); ++ pispbe_wr(pispbe, PISP_BE_IO_ADDR_HIGH(u), ++ upper_32_bits(job->hw_dma_addrs[u])); ++ } ++ pispbe_wr(pispbe, PISP_BE_GLOBAL_BAYER_ENABLE, ++ job->hw_enables.bayer_enables); ++ pispbe_wr(pispbe, PISP_BE_GLOBAL_RGB_ENABLE, ++ job->hw_enables.rgb_enables); + +- /* +- * Everything else is as supplied by the user. XXX Buffer sizes not +- * checked! +- */ ++ /* Everything else is as supplied by the user. */ + begin = offsetof(struct pisp_be_config, global.bayer_order) / +- sizeof(u32); +- end = offsetof(struct pisp_be_config, axi) / sizeof(u32); +- for (u = begin; u < end; u++) { +- unsigned int val = ((u32 *)config)[u]; +- +- write_reg(pispbe, PISP_BE_CONFIG_BASE_OFFSET + 4 * u, val); +- } ++ sizeof(u32); ++ end = sizeof(struct pisp_be_config) / sizeof(u32); ++ for (unsigned int u = begin; u < end; u++) ++ pispbe_wr(pispbe, PISP_BE_CONFIG_BASE_REG + sizeof(u32) * u, ++ ((u32 *)job->config)[u]); + + /* Read back the addresses -- an error here could be fatal */ +- for (u = 0; u < N_HW_ADDRESSES; ++u) { +- unsigned int offset = PISP_BE_IO_INPUT_ADDR0_LO_OFFSET + 8 * u; +- u64 along = read_reg(pispbe, offset); +- +- along += ((u64)read_reg(pispbe, offset + 4)) << 32; +- if (along != (u64)(hw_dma_addrs[u])) { +- dev_err(pispbe->dev, ++ for (unsigned int u = 0; u < N_HW_ADDRESSES; ++u) { ++ unsigned int offset = PISP_BE_IO_ADDR_LOW(u); ++ u64 along = pispbe_rd(pispbe, offset); ++ ++ along += ((u64)pispbe_rd(pispbe, offset + 4)) << 32; ++ if (along != (u64)(job->hw_dma_addrs[u])) { ++ dev_dbg(pispbe->dev, + "ISP BE config error: check if ISP RAMs enabled?\n"); + return; + } + } + + /* +- * Write tile pointer to hardware. XXX Tile offsets and sizes not +- * checked (and even if checked, the user could subsequently modify +- * them)! ++ * Write tile pointer to hardware. The IOMMU should prevent ++ * out-of-bounds offsets reaching non-ISP buffers. + */ +- write_reg(pispbe, PISP_BE_TILE_ADDR_LO_OFFSET, (u32)tiles); +- write_reg(pispbe, PISP_BE_TILE_ADDR_HI_OFFSET, (u32)(tiles >> 32)); ++ pispbe_wr(pispbe, PISP_BE_TILE_ADDR_LO_REG, lower_32_bits(job->tiles)); ++ pispbe_wr(pispbe, PISP_BE_TILE_ADDR_HI_REG, upper_32_bits(job->tiles)); + + /* Enqueue the job */ +- write_reg(pispbe, PISP_BE_CONTROL_OFFSET, 3 + 65536 * num_tiles); ++ pispbe_wr(pispbe, PISP_BE_CONTROL_REG, ++ PISP_BE_CONTROL_COPY_CONFIG | PISP_BE_CONTROL_QUEUE_JOB | ++ PISP_BE_CONTROL_NUM_TILES(job->config->num_tiles)); + } + + struct pispbe_buffer { +@@ -356,8 +302,8 @@ struct pispbe_buffer { + unsigned int config_index; + }; + +-static int get_addr_3(dma_addr_t addr[3], struct pispbe_buffer *buf, +- struct pispbe_node *node) ++static int pispbe_get_planes_addr(dma_addr_t addr[3], struct pispbe_buffer *buf, ++ struct pispbe_node *node) + { + unsigned int num_planes = node->format.fmt.pix_mp.num_planes; + unsigned int plane_factor = 0; +@@ -367,22 +313,20 @@ static int get_addr_3(dma_addr_t addr[3] + if (!buf || !node->pisp_format) + return 0; + +- WARN_ON(!NODE_IS_MPLANE(node)); +- + /* + * Determine the base plane size. This will not be the same + * as node->format.fmt.pix_mp.plane_fmt[0].sizeimage for a single + * plane buffer in an mplane format. + */ + size = node->format.fmt.pix_mp.plane_fmt[0].bytesperline * +- node->format.fmt.pix_mp.height; ++ node->format.fmt.pix_mp.height; + +- for (p = 0; p < num_planes && p < 3; p++) { ++ for (p = 0; p < num_planes && p < PISPBE_MAX_PLANES; p++) { + addr[p] = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, p); + plane_factor += node->pisp_format->plane_factor[p]; + } + +- for (; p < MAX_PLANES && node->pisp_format->plane_factor[p]; p++) { ++ for (; p < PISPBE_MAX_PLANES && node->pisp_format->plane_factor[p]; p++) { + /* + * Calculate the address offset of this plane as needed + * by the hardware. This is specifically for non-mplane +@@ -396,41 +340,41 @@ static int get_addr_3(dma_addr_t addr[3] + return num_planes; + } + +-static dma_addr_t get_addr(struct pispbe_buffer *buf) ++static dma_addr_t pispbe_get_addr(struct pispbe_buffer *buf) + { + if (buf) + return vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); ++ + return 0; + } + +-static void +-fixup_addrs_enables(dma_addr_t addrs[N_HW_ADDRESSES], +- u32 hw_enables[N_HW_ENABLES], +- struct pisp_be_tiles_config *config, +- struct pispbe_buffer *buf[PISPBE_NUM_NODES], +- struct pispbe_node_group *node_group) +-{ +- int ret, i; ++static void pispbe_xlate_addrs(struct pispbe_dev *pispbe, ++ struct pispbe_job_descriptor *job, ++ struct pispbe_buffer *buf[PISPBE_NUM_NODES]) ++{ ++ struct pispbe_hw_enables *hw_en = &job->hw_enables; ++ struct pisp_be_tiles_config *config = job->config; ++ dma_addr_t *addrs = job->hw_dma_addrs; ++ int ret; + + /* Take a copy of the "enable" bitmaps so we can modify them. */ +- hw_enables[0] = config->config.global.bayer_enables; +- hw_enables[1] = config->config.global.rgb_enables; ++ hw_en->bayer_enables = config->config.global.bayer_enables; ++ hw_en->rgb_enables = config->config.global.rgb_enables; + + /* + * Main input first. There are 3 address pointers, corresponding to up + * to 3 planes. + */ +- ret = get_addr_3(addrs, buf[MAIN_INPUT_NODE], +- &node_group->node[MAIN_INPUT_NODE]); ++ ret = pispbe_get_planes_addr(addrs, buf[MAIN_INPUT_NODE], ++ &pispbe->node[MAIN_INPUT_NODE]); + if (ret <= 0) { + /* + * This shouldn't happen; pispbe_schedule_internal should insist + * on an input. + */ +- dev_warn(node_group->pispbe->dev, +- "ISP-BE missing input\n"); +- hw_enables[0] = 0; +- hw_enables[1] = 0; ++ dev_warn(pispbe->dev, "ISP-BE missing input\n"); ++ hw_en->bayer_enables = 0; ++ hw_en->rgb_enables = 0; + return; + } + +@@ -439,118 +383,114 @@ fixup_addrs_enables(dma_addr_t addrs[N_H + * used with Bayer input. Input enables must match the requirements + * of the processing stages, otherwise the hardware can lock up! + */ +- if (hw_enables[0] & PISP_BE_BAYER_ENABLE_INPUT) { +- addrs[3] = get_addr(buf[TDN_INPUT_NODE]); ++ if (hw_en->bayer_enables & PISP_BE_BAYER_ENABLE_INPUT) { ++ addrs[3] = pispbe_get_addr(buf[TDN_INPUT_NODE]); + if (addrs[3] == 0 || +- !(hw_enables[0] & PISP_BE_BAYER_ENABLE_TDN_INPUT) || +- !(hw_enables[0] & PISP_BE_BAYER_ENABLE_TDN) || ++ !(hw_en->bayer_enables & PISP_BE_BAYER_ENABLE_TDN_INPUT) || ++ !(hw_en->bayer_enables & PISP_BE_BAYER_ENABLE_TDN) || + (config->config.tdn.reset & 1)) { +- hw_enables[0] &= ~(PISP_BE_BAYER_ENABLE_TDN_INPUT | +- PISP_BE_BAYER_ENABLE_TDN_DECOMPRESS); ++ hw_en->bayer_enables &= ++ ~(PISP_BE_BAYER_ENABLE_TDN_INPUT | ++ PISP_BE_BAYER_ENABLE_TDN_DECOMPRESS); + if (!(config->config.tdn.reset & 1)) +- hw_enables[0] &= ~PISP_BE_BAYER_ENABLE_TDN; ++ hw_en->bayer_enables &= ++ ~PISP_BE_BAYER_ENABLE_TDN; + } + +- addrs[4] = get_addr(buf[STITCH_INPUT_NODE]); ++ addrs[4] = pispbe_get_addr(buf[STITCH_INPUT_NODE]); + if (addrs[4] == 0 || +- !(hw_enables[0] & PISP_BE_BAYER_ENABLE_STITCH_INPUT) || +- !(hw_enables[0] & PISP_BE_BAYER_ENABLE_STITCH)) { +- hw_enables[0] &= ++ !(hw_en->bayer_enables & PISP_BE_BAYER_ENABLE_STITCH_INPUT) || ++ !(hw_en->bayer_enables & PISP_BE_BAYER_ENABLE_STITCH)) { ++ hw_en->bayer_enables &= + ~(PISP_BE_BAYER_ENABLE_STITCH_INPUT | + PISP_BE_BAYER_ENABLE_STITCH_DECOMPRESS | + PISP_BE_BAYER_ENABLE_STITCH); + } + +- addrs[5] = get_addr(buf[TDN_OUTPUT_NODE]); ++ addrs[5] = pispbe_get_addr(buf[TDN_OUTPUT_NODE]); + if (addrs[5] == 0) +- hw_enables[0] &= ~(PISP_BE_BAYER_ENABLE_TDN_COMPRESS | +- PISP_BE_BAYER_ENABLE_TDN_OUTPUT); ++ hw_en->bayer_enables &= ++ ~(PISP_BE_BAYER_ENABLE_TDN_COMPRESS | ++ PISP_BE_BAYER_ENABLE_TDN_OUTPUT); + +- addrs[6] = get_addr(buf[STITCH_OUTPUT_NODE]); ++ addrs[6] = pispbe_get_addr(buf[STITCH_OUTPUT_NODE]); + if (addrs[6] == 0) +- hw_enables[0] &= ++ hw_en->bayer_enables &= + ~(PISP_BE_BAYER_ENABLE_STITCH_COMPRESS | + PISP_BE_BAYER_ENABLE_STITCH_OUTPUT); + } else { + /* No Bayer input? Disable entire Bayer pipe (else lockup) */ +- hw_enables[0] = 0; ++ hw_en->bayer_enables = 0; + } + + /* Main image output channels. */ +- for (i = 0; i < PISP_BACK_END_NUM_OUTPUTS; i++) { +- ret = get_addr_3(addrs + 7 + 3 * i, buf[OUTPUT0_NODE + i], +- &node_group->node[OUTPUT0_NODE + i]); ++ for (unsigned int i = 0; i < PISP_BACK_END_NUM_OUTPUTS; i++) { ++ ret = pispbe_get_planes_addr(addrs + 7 + 3 * i, ++ buf[OUTPUT0_NODE + i], ++ &pispbe->node[OUTPUT0_NODE + i]); + if (ret <= 0) +- hw_enables[1] &= ~(PISP_BE_RGB_ENABLE_OUTPUT0 << i); ++ hw_en->rgb_enables &= ~(PISP_BE_RGB_ENABLE_OUTPUT0 << i); + } +- +- /* HoG output (always single plane). */ +- addrs[13] = get_addr(buf[HOG_OUTPUT_NODE]); +- if (addrs[13] == 0) +- hw_enables[1] &= ~PISP_BE_RGB_ENABLE_HOG; + } + + /* +- * Internal function. Called from pispbe_schedule_one/all. Returns non-zero if +- * we started a job. ++ * Prepare a job description to be submitted to the HW. ++ * ++ * To schedule a job, we need all streaming nodes (apart from Output0, ++ * Output1, Tdn and Stitch) to have a buffer ready, which must ++ * include at least a config buffer and a main input image. + * +- * Warning: needs to be called with hw_lock taken, and releases it if it +- * schedules a job. ++ * For Output0, Output1, Tdn and Stitch, a buffer only needs to be ++ * available if the blocks are enabled in the config. ++ * ++ * Needs to be called with hw_lock held. ++ * ++ * Returns 0 if a job has been successfully prepared, < 0 otherwise. + */ +-static int pispbe_schedule_internal(struct pispbe_node_group *node_group, +- unsigned long flags) ++static int pispbe_prepare_job(struct pispbe_dev *pispbe, ++ struct pispbe_job_descriptor *job) + { +- struct pisp_be_tiles_config *config_tiles_buffer; +- struct pispbe_dev *pispbe = node_group->pispbe; +- struct pispbe_buffer *buf[PISPBE_NUM_NODES]; +- dma_addr_t hw_dma_addrs[N_HW_ADDRESSES]; +- dma_addr_t tiles; +- u32 hw_enables[N_HW_ENABLES]; +- struct pispbe_node *node; +- unsigned long flags1; ++ struct pispbe_buffer *buf[PISPBE_NUM_NODES] = {}; + unsigned int config_index; +- int i; ++ struct pispbe_node *node; ++ unsigned long flags; ++ ++ lockdep_assert_held(&pispbe->hw_lock); ++ ++ memset(job, 0, sizeof(struct pispbe_job_descriptor)); + +- /* +- * To schedule a job, we need all streaming nodes (apart from Output0, +- * Output1, Tdn and Stitch) to have a buffer ready, which must +- * include at least a config buffer and a main input image. +- * +- * For Output0, Output1, Tdn and Stitch, a buffer only needs to be +- * available if the blocks are enabled in the config. +- * +- * (Note that streaming_map is protected by hw_lock, which is held.) +- */ + if (((BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE)) & +- node_group->streaming_map) != +- (BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE))) { +- dev_dbg(pispbe->dev, "Nothing to do\n"); +- return 0; +- } ++ pispbe->streaming_map) != ++ (BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE))) ++ return -ENODEV; + +- node = &node_group->node[CONFIG_NODE]; +- spin_lock_irqsave(&node->ready_lock, flags1); +- buf[CONFIG_NODE] = +- list_first_entry_or_null(&node->ready_queue, struct pispbe_buffer, +- ready_list); +- spin_unlock_irqrestore(&node->ready_lock, flags1); ++ node = &pispbe->node[CONFIG_NODE]; ++ spin_lock_irqsave(&node->ready_lock, flags); ++ buf[CONFIG_NODE] = list_first_entry_or_null(&node->ready_queue, ++ struct pispbe_buffer, ++ ready_list); ++ if (buf[CONFIG_NODE]) { ++ list_del(&buf[CONFIG_NODE]->ready_list); ++ pispbe->queued_job.buf[CONFIG_NODE] = buf[CONFIG_NODE]; ++ } ++ spin_unlock_irqrestore(&node->ready_lock, flags); + + /* Exit early if no config buffer has been queued. */ + if (!buf[CONFIG_NODE]) +- return 0; ++ return -ENODEV; + + config_index = buf[CONFIG_NODE]->vb.vb2_buf.index; +- config_tiles_buffer = &node_group->config[config_index]; +- tiles = (dma_addr_t)node_group->config_dma_addr + +- config_index * sizeof(struct pisp_be_tiles_config) + +- offsetof(struct pisp_be_tiles_config, tiles); ++ job->config = &pispbe->config[config_index]; ++ job->tiles = pispbe->config_dma_addr + ++ config_index * sizeof(struct pisp_be_tiles_config) + ++ offsetof(struct pisp_be_tiles_config, tiles); + + /* remember: srcimages, captures then metadata */ +- for (i = 0; i < PISPBE_NUM_NODES; i++) { ++ for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) { + unsigned int bayer_en = +- config_tiles_buffer->config.global.bayer_enables; ++ job->config->config.global.bayer_enables; + unsigned int rgb_en = +- config_tiles_buffer->config.global.rgb_enables; ++ job->config->config.global.rgb_enables; + bool ignore_buffers = false; + + /* Config node is handled outside the loop above. */ +@@ -558,7 +498,7 @@ static int pispbe_schedule_internal(stru + continue; + + buf[i] = NULL; +- if (!(node_group->streaming_map & BIT(i))) ++ if (!(pispbe->streaming_map & BIT(i))) + continue; + + if ((!(rgb_en & PISP_BE_RGB_ENABLE_OUTPUT0) && +@@ -578,119 +518,103 @@ static int pispbe_schedule_internal(stru + * global enables aren't set for these blocks. If a + * buffer has been provided, we dequeue it back to the + * user with the other in-use buffers. +- * + */ + ignore_buffers = true; + } + +- node = &node_group->node[i]; ++ node = &pispbe->node[i]; + +- spin_lock_irqsave(&node->ready_lock, flags1); ++ /* Pull a buffer from each V4L2 queue to form the queued job */ ++ spin_lock_irqsave(&node->ready_lock, flags); + buf[i] = list_first_entry_or_null(&node->ready_queue, + struct pispbe_buffer, + ready_list); +- spin_unlock_irqrestore(&node->ready_lock, flags1); +- if (!buf[i] && !ignore_buffers) { +- dev_dbg(pispbe->dev, "Nothing to do\n"); +- return 0; +- } +- } +- +- /* Pull a buffer from each V4L2 queue to form the queued job */ +- for (i = 0; i < PISPBE_NUM_NODES; i++) { + if (buf[i]) { +- node = &node_group->node[i]; +- +- spin_lock_irqsave(&node->ready_lock, flags1); + list_del(&buf[i]->ready_list); +- spin_unlock_irqrestore(&node->ready_lock, +- flags1); ++ pispbe->queued_job.buf[i] = buf[i]; + } +- pispbe->queued_job.buf[i] = buf[i]; ++ spin_unlock_irqrestore(&node->ready_lock, flags); ++ ++ if (!buf[i] && !ignore_buffers) ++ goto err_return_buffers; + } + +- pispbe->queued_job.node_group = node_group; +- pispbe->hw_busy = 1; +- spin_unlock_irqrestore(&pispbe->hw_lock, flags); +- +- /* +- * We can kick the job off without the hw_lock, as this can +- * never run again until hw_busy is cleared, which will happen +- * only when the following job has been queued. +- */ +- dev_dbg(pispbe->dev, "Have buffers - starting hardware\n"); ++ pispbe->queued_job.valid = true; + + /* Convert buffers to DMA addresses for the hardware */ +- fixup_addrs_enables(hw_dma_addrs, hw_enables, +- config_tiles_buffer, buf, node_group); +- /* +- * This could be a spot to fill in the +- * buf[i]->vb.vb2_buf.planes[j].bytesused fields? +- */ +- i = config_tiles_buffer->num_tiles; +- if (i <= 0 || i > PISP_BACK_END_NUM_TILES || +- !((hw_enables[0] | hw_enables[1]) & +- PISP_BE_BAYER_ENABLE_INPUT)) { +- /* +- * Bad job. We can't let it proceed as it could lock up +- * the hardware, or worse! +- * +- * XXX How to deal with this most cleanly? For now, just +- * force num_tiles to 0, which causes the H/W to do +- * something bizarre but survivable. It increments +- * (started,done) counters by more than 1, but we seem +- * to survive... +- */ +- dev_err(pispbe->dev, "PROBLEM: Bad job"); +- i = 0; +- } +- hw_queue_job(pispbe, hw_dma_addrs, hw_enables, +- &config_tiles_buffer->config, tiles, i); ++ pispbe_xlate_addrs(pispbe, job, buf); + +- return 1; +-} ++ return 0; + +-/* Try and schedule a job for just a single node group. */ +-static void pispbe_schedule_one(struct pispbe_node_group *node_group) +-{ +- struct pispbe_dev *pispbe = node_group->pispbe; +- unsigned long flags; +- int ret; ++err_return_buffers: ++ for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) { ++ struct pispbe_node *n = &pispbe->node[i]; + +- spin_lock_irqsave(&pispbe->hw_lock, flags); +- if (pispbe->hw_busy) { +- spin_unlock_irqrestore(&pispbe->hw_lock, flags); +- return; ++ if (!buf[i]) ++ continue; ++ ++ /* Return the buffer to the ready_list queue */ ++ spin_lock_irqsave(&n->ready_lock, flags); ++ list_add(&buf[i]->ready_list, &n->ready_queue); ++ spin_unlock_irqrestore(&n->ready_lock, flags); + } + +- /* A non-zero return means the lock was released. */ +- ret = pispbe_schedule_internal(node_group, flags); +- if (!ret) +- spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ memset(&pispbe->queued_job, 0, sizeof(pispbe->queued_job)); ++ ++ return -ENODEV; + } + +-/* Try and schedule a job for any of the node groups. */ +-static void pispbe_schedule_any(struct pispbe_dev *pispbe, int clear_hw_busy) ++static void pispbe_schedule(struct pispbe_dev *pispbe, bool clear_hw_busy) + { ++ struct pispbe_job_descriptor job; + unsigned long flags; ++ int ret; + + spin_lock_irqsave(&pispbe->hw_lock, flags); + + if (clear_hw_busy) +- pispbe->hw_busy = 0; +- if (pispbe->hw_busy == 0) { +- unsigned int i; ++ pispbe->hw_busy = false; + +- for (i = 0; i < PISPBE_NUM_NODE_GROUPS; i++) { +- /* +- * A non-zero return from pispbe_schedule_internal means +- * the lock was released. +- */ +- if (pispbe_schedule_internal(&pispbe->node_group[i], +- flags)) +- return; +- } ++ if (pispbe->hw_busy) ++ goto unlock_and_return; ++ ++ ret = pispbe_prepare_job(pispbe, &job); ++ if (ret) ++ goto unlock_and_return; ++ ++ /* ++ * We can kick the job off without the hw_lock, as this can ++ * never run again until hw_busy is cleared, which will happen ++ * only when the following job has been queued and an interrupt ++ * is rised. ++ */ ++ pispbe->hw_busy = true; ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ ++ if (job.config->num_tiles <= 0 || ++ job.config->num_tiles > PISP_BACK_END_NUM_TILES || ++ !((job.hw_enables.bayer_enables | job.hw_enables.rgb_enables) & ++ PISP_BE_BAYER_ENABLE_INPUT)) { ++ /* ++ * Bad job. We can't let it proceed as it could lock up ++ * the hardware, or worse! ++ * ++ * For now, just force num_tiles to 0, which causes the ++ * H/W to do something bizarre but survivable. It ++ * increments (started,done) counters by more than 1, ++ * but we seem to survive... ++ */ ++ dev_dbg(pispbe->dev, "Bad job: invalid number of tiles: %u\n", ++ job.config->num_tiles); ++ job.config->num_tiles = 0; + } ++ ++ pispbe_queue_job(pispbe, &job); ++ ++ return; ++ ++unlock_and_return: ++ /* No job has been queued, just release the lock and return. */ + spin_unlock_irqrestore(&pispbe->hw_lock, flags); + } + +@@ -699,62 +623,53 @@ static void pispbe_isr_jobdone(struct pi + { + struct pispbe_buffer **buf = job->buf; + u64 ts = ktime_get_ns(); +- int i; + +- for (i = 0; i < PISPBE_NUM_NODES; i++) { ++ for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) { + if (buf[i]) { + buf[i]->vb.vb2_buf.timestamp = ts; +- buf[i]->vb.sequence = job->node_group->sequence; ++ buf[i]->vb.sequence = pispbe->sequence; + vb2_buffer_done(&buf[i]->vb.vb2_buf, + VB2_BUF_STATE_DONE); + } + } + +- job->node_group->sequence++; ++ pispbe->sequence++; + } + + static irqreturn_t pispbe_isr(int irq, void *dev) + { + struct pispbe_dev *pispbe = (struct pispbe_dev *)dev; ++ bool can_queue_another = false; + u8 started, done; +- int can_queue_another = 0; + u32 u; + +- u = read_reg(pispbe, PISP_BE_INTERRUPT_STATUS_OFFSET); ++ u = pispbe_rd(pispbe, PISP_BE_INTERRUPT_STATUS_REG); + if (u == 0) + return IRQ_NONE; + +- write_reg(pispbe, PISP_BE_INTERRUPT_STATUS_OFFSET, u); +- dev_dbg(pispbe->dev, "Hardware interrupt\n"); +- u = read_reg(pispbe, PISP_BE_BATCH_STATUS_OFFSET); ++ pispbe_wr(pispbe, PISP_BE_INTERRUPT_STATUS_REG, u); ++ u = pispbe_rd(pispbe, PISP_BE_BATCH_STATUS_REG); + done = (uint8_t)u; + started = (uint8_t)(u >> 8); +- dev_dbg(pispbe->dev, +- "H/W started %d done %d, previously started %d done %d\n", +- (int)started, (int)done, (int)pispbe->started, +- (int)pispbe->done); + + /* + * Be aware that done can go up by 2 and started by 1 when: a job that + * we previously saw "start" now finishes, and we then queued a new job + * which we see both start and finish "simultaneously". + */ +- if (pispbe->running_job.node_group && pispbe->done != done) { ++ if (pispbe->running_job.valid && pispbe->done != done) { + pispbe_isr_jobdone(pispbe, &pispbe->running_job); + memset(&pispbe->running_job, 0, sizeof(pispbe->running_job)); + pispbe->done++; +- dev_dbg(pispbe->dev, "Job done (1)\n"); + } + + if (pispbe->started != started) { + pispbe->started++; + can_queue_another = 1; +- dev_dbg(pispbe->dev, "Job started\n"); + +- if (pispbe->done != done && pispbe->queued_job.node_group) { ++ if (pispbe->done != done && pispbe->queued_job.valid) { + pispbe_isr_jobdone(pispbe, &pispbe->queued_job); + pispbe->done++; +- dev_dbg(pispbe->dev, "Job done (2)\n"); + } else { + pispbe->running_job = pispbe->queued_job; + } +@@ -763,74 +678,81 @@ static irqreturn_t pispbe_isr(int irq, v + } + + if (pispbe->done != done || pispbe->started != started) { +- dev_err(pispbe->dev, "PROBLEM: counters not matching!\n"); ++ dev_dbg(pispbe->dev, ++ "Job counters not matching: done = %u, expected %u - started = %u, expected %u\n", ++ pispbe->done, done, pispbe->started, started); + pispbe->started = started; + pispbe->done = done; + } + + /* check if there's more to do before going to sleep */ +- pispbe_schedule_any(pispbe, can_queue_another); ++ pispbe_schedule(pispbe, can_queue_another); + + return IRQ_HANDLED; + } + +-static int pisp_be_validate_config(struct pispbe_node_group *node_group, ++static int pisp_be_validate_config(struct pispbe_dev *pispbe, + struct pisp_be_tiles_config *config) + { + u32 bayer_enables = config->config.global.bayer_enables; + u32 rgb_enables = config->config.global.rgb_enables; +- struct device *dev = node_group->pispbe->dev; ++ struct device *dev = pispbe->dev; + struct v4l2_format *fmt; +- unsigned int bpl, size, i, j; ++ unsigned int bpl, size; + + if (!(bayer_enables & PISP_BE_BAYER_ENABLE_INPUT) == + !(rgb_enables & PISP_BE_RGB_ENABLE_INPUT)) { +- dev_err(dev, "%s: Not one input enabled\n", __func__); ++ dev_dbg(dev, "%s: Not one input enabled\n", __func__); + return -EIO; + } + + /* Ensure output config strides and buffer sizes match the V4L2 formats. */ +- fmt = &node_group->node[TDN_OUTPUT_NODE].format; ++ fmt = &pispbe->node[TDN_OUTPUT_NODE].format; + if (bayer_enables & PISP_BE_BAYER_ENABLE_TDN_OUTPUT) { + bpl = config->config.tdn_output_format.stride; + size = bpl * config->config.tdn_output_format.height; ++ + if (fmt->fmt.pix_mp.plane_fmt[0].bytesperline < bpl) { +- dev_err(dev, "%s: bpl mismatch on tdn_output\n", ++ dev_dbg(dev, "%s: bpl mismatch on tdn_output\n", + __func__); + return -EINVAL; + } ++ + if (fmt->fmt.pix_mp.plane_fmt[0].sizeimage < size) { +- dev_err(dev, "%s: size mismatch on tdn_output\n", ++ dev_dbg(dev, "%s: size mismatch on tdn_output\n", + __func__); + return -EINVAL; + } + } + +- fmt = &node_group->node[STITCH_OUTPUT_NODE].format; ++ fmt = &pispbe->node[STITCH_OUTPUT_NODE].format; + if (bayer_enables & PISP_BE_BAYER_ENABLE_STITCH_OUTPUT) { + bpl = config->config.stitch_output_format.stride; + size = bpl * config->config.stitch_output_format.height; ++ + if (fmt->fmt.pix_mp.plane_fmt[0].bytesperline < bpl) { +- dev_err(dev, "%s: bpl mismatch on stitch_output\n", ++ dev_dbg(dev, "%s: bpl mismatch on stitch_output\n", + __func__); + return -EINVAL; + } ++ + if (fmt->fmt.pix_mp.plane_fmt[0].sizeimage < size) { +- dev_err(dev, "%s: size mismatch on stitch_output\n", ++ dev_dbg(dev, "%s: size mismatch on stitch_output\n", + __func__); + return -EINVAL; + } + } + +- for (j = 0; j < PISP_BACK_END_NUM_OUTPUTS; j++) { ++ for (unsigned int j = 0; j < PISP_BACK_END_NUM_OUTPUTS; j++) { + if (!(rgb_enables & PISP_BE_RGB_ENABLE_OUTPUT(j))) + continue; ++ + if (config->config.output_format[j].image.format & + PISP_IMAGE_FORMAT_WALLPAPER_ROLL) + continue; /* TODO: Size checks for wallpaper formats */ + +- fmt = &node_group->node[OUTPUT0_NODE + j].format; +- for (i = 0; i < fmt->fmt.pix_mp.num_planes; i++) { ++ fmt = &pispbe->node[OUTPUT0_NODE + j].format; ++ for (unsigned int i = 0; i < fmt->fmt.pix_mp.num_planes; i++) { + bpl = !i ? config->config.output_format[j].image.stride + : config->config.output_format[j].image.stride2; + size = bpl * config->config.output_format[j].image.height; +@@ -838,13 +760,15 @@ static int pisp_be_validate_config(struc + if (config->config.output_format[j].image.format & + PISP_IMAGE_FORMAT_SAMPLING_420) + size >>= 1; ++ + if (fmt->fmt.pix_mp.plane_fmt[i].bytesperline < bpl) { +- dev_err(dev, "%s: bpl mismatch on output %d\n", ++ dev_dbg(dev, "%s: bpl mismatch on output %d\n", + __func__, j); + return -EINVAL; + } ++ + if (fmt->fmt.pix_mp.plane_fmt[i].sizeimage < size) { +- dev_err(dev, "%s: size mismatch on output\n", ++ dev_dbg(dev, "%s: size mismatch on output\n", + __func__); + return -EINVAL; + } +@@ -859,32 +783,32 @@ static int pispbe_node_queue_setup(struc + struct device *alloc_devs[]) + { + struct pispbe_node *node = vb2_get_drv_priv(q); +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; ++ unsigned int num_planes = NODE_IS_MPLANE(node) ? ++ node->format.fmt.pix_mp.num_planes : 1; + +- *nplanes = 1; +- if (NODE_IS_MPLANE(node)) { +- unsigned int i; +- +- *nplanes = node->format.fmt.pix_mp.num_planes; +- for (i = 0; i < *nplanes; i++) { +- unsigned int size = +- node->format.fmt.pix_mp.plane_fmt[i].sizeimage; +- if (sizes[i] && sizes[i] < size) { +- dev_err(pispbe->dev, "%s: size %u < %u\n", +- __func__, sizes[i], size); ++ if (*nplanes) { ++ if (*nplanes != num_planes) ++ return -EINVAL; ++ ++ for (unsigned int i = 0; i < *nplanes; i++) { ++ unsigned int size = NODE_IS_MPLANE(node) ? ++ node->format.fmt.pix_mp.plane_fmt[i].sizeimage : ++ node->format.fmt.meta.buffersize; ++ ++ if (sizes[i] < size) + return -EINVAL; +- } +- sizes[i] = size; + } +- } else if (NODE_IS_META(node)) { +- sizes[0] = node->format.fmt.meta.buffersize; +- /* +- * Limit the config node buffer count to the number of internal +- * buffers allocated. +- */ +- if (node->id == CONFIG_NODE) +- *nbuffers = min_t(unsigned int, *nbuffers, +- PISP_BE_NUM_CONFIG_BUFFERS); ++ ++ return 0; ++ } ++ ++ *nplanes = num_planes; ++ for (unsigned int i = 0; i < *nplanes; i++) { ++ unsigned int size = NODE_IS_MPLANE(node) ? ++ node->format.fmt.pix_mp.plane_fmt[i].sizeimage : ++ node->format.fmt.meta.buffersize; ++ sizes[i] = size; + } + + dev_dbg(pispbe->dev, +@@ -897,19 +821,17 @@ static int pispbe_node_queue_setup(struc + static int pispbe_node_buffer_prepare(struct vb2_buffer *vb) + { + struct pispbe_node *node = vb2_get_drv_priv(vb->vb2_queue); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- unsigned long size = 0; ++ struct pispbe_dev *pispbe = node->pispbe; + unsigned int num_planes = NODE_IS_MPLANE(node) ? +- node->format.fmt.pix_mp.num_planes : 1; +- unsigned int i; ++ node->format.fmt.pix_mp.num_planes : 1; + +- for (i = 0; i < num_planes; i++) { +- size = NODE_IS_MPLANE(node) +- ? node->format.fmt.pix_mp.plane_fmt[i].sizeimage +- : node->format.fmt.meta.buffersize; ++ for (unsigned int i = 0; i < num_planes; i++) { ++ unsigned long size = NODE_IS_MPLANE(node) ? ++ node->format.fmt.pix_mp.plane_fmt[i].sizeimage : ++ node->format.fmt.meta.buffersize; + + if (vb2_plane_size(vb, i) < size) { +- dev_err(pispbe->dev, ++ dev_dbg(pispbe->dev, + "data will not fit into plane %d (%lu < %lu)\n", + i, vb2_plane_size(vb, i), size); + return -EINVAL; +@@ -919,11 +841,12 @@ static int pispbe_node_buffer_prepare(st + } + + if (node->id == CONFIG_NODE) { +- void *dst = &node->node_group->config[vb->index]; ++ void *dst = &node->pispbe->config[vb->index]; + void *src = vb2_plane_vaddr(vb, 0); + + memcpy(dst, src, sizeof(struct pisp_be_tiles_config)); +- return pisp_be_validate_config(node->node_group, dst); ++ ++ return pisp_be_validate_config(pispbe, dst); + } + + return 0; +@@ -936,8 +859,7 @@ static void pispbe_node_buffer_queue(str + struct pispbe_buffer *buffer = + container_of(vbuf, struct pispbe_buffer, vb); + struct pispbe_node *node = vb2_get_drv_priv(buf->vb2_queue); +- struct pispbe_node_group *node_group = node->node_group; +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; + unsigned long flags; + + dev_dbg(pispbe->dev, "%s: for node %s\n", __func__, NODE_NAME(node)); +@@ -947,44 +869,53 @@ static void pispbe_node_buffer_queue(str + + /* + * Every time we add a buffer, check if there's now some work for the hw +- * to do, but only for this client. ++ * to do. + */ +- pispbe_schedule_one(node_group); ++ pispbe_schedule(pispbe, false); + } + + static int pispbe_node_start_streaming(struct vb2_queue *q, unsigned int count) + { +- unsigned long flags; + struct pispbe_node *node = vb2_get_drv_priv(q); +- struct pispbe_node_group *node_group = node->node_group; +- struct pispbe_dev *pispbe = node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_buffer *buf, *tmp; ++ unsigned long flags; + int ret; + + ret = pm_runtime_resume_and_get(pispbe->dev); + if (ret < 0) +- return ret; ++ goto err_return_buffers; + + spin_lock_irqsave(&pispbe->hw_lock, flags); +- node->node_group->streaming_map |= BIT(node->id); +- node->node_group->sequence = 0; ++ node->pispbe->streaming_map |= BIT(node->id); ++ node->pispbe->sequence = 0; + spin_unlock_irqrestore(&pispbe->hw_lock, flags); + + dev_dbg(pispbe->dev, "%s: for node %s (count %u)\n", + __func__, NODE_NAME(node), count); +- dev_dbg(pispbe->dev, "Nodes streaming for this group now 0x%x\n", +- node->node_group->streaming_map); ++ dev_dbg(pispbe->dev, "Nodes streaming now 0x%x\n", ++ node->pispbe->streaming_map); + + /* Maybe we're ready to run. */ +- pispbe_schedule_one(node_group); ++ pispbe_schedule(pispbe, false); + + return 0; ++ ++err_return_buffers: ++ spin_lock_irqsave(&pispbe->hw_lock, flags); ++ list_for_each_entry_safe(buf, tmp, &node->ready_queue, ready_list) { ++ list_del(&buf->ready_list); ++ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); ++ } ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ ++ return ret; + } + + static void pispbe_node_stop_streaming(struct vb2_queue *q) + { + struct pispbe_node *node = vb2_get_drv_priv(q); +- struct pispbe_node_group *node_group = node->node_group; +- struct pispbe_dev *pispbe = node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; + struct pispbe_buffer *buf; + unsigned long flags; + +@@ -994,7 +925,8 @@ static void pispbe_node_stop_streaming(s + * partial set of buffers was queued and cannot be run. For now, just + * cancel all buffers stuck in the "ready queue", then wait for any + * running job. +- * XXX This may return buffers out of order. ++ * ++ * This may return buffers out of order. + */ + dev_dbg(pispbe->dev, "%s: for node %s\n", __func__, NODE_NAME(node)); + spin_lock_irqsave(&pispbe->hw_lock, flags); +@@ -1016,14 +948,14 @@ static void pispbe_node_stop_streaming(s + vb2_wait_for_all_buffers(&node->queue); + + spin_lock_irqsave(&pispbe->hw_lock, flags); +- node_group->streaming_map &= ~BIT(node->id); ++ pispbe->streaming_map &= ~BIT(node->id); + spin_unlock_irqrestore(&pispbe->hw_lock, flags); + + pm_runtime_mark_last_busy(pispbe->dev); + pm_runtime_put_autosuspend(pispbe->dev); + +- dev_dbg(pispbe->dev, "Nodes streaming for this group now 0x%x\n", +- node_group->streaming_map); ++ dev_dbg(pispbe->dev, "Nodes streaming now 0x%x\n", ++ pispbe->streaming_map); + } + + static const struct vb2_ops pispbe_node_queue_ops = { +@@ -1047,22 +979,15 @@ static int pispbe_node_querycap(struct f + struct v4l2_capability *cap) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; + + strscpy(cap->driver, PISPBE_NAME, sizeof(cap->driver)); + strscpy(cap->card, PISPBE_NAME, sizeof(cap->card)); +- snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", +- dev_name(pispbe->dev)); +- +- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE | +- V4L2_CAP_VIDEO_OUTPUT_MPLANE | +- V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS | +- V4L2_CAP_META_OUTPUT | V4L2_CAP_META_CAPTURE; +- cap->device_caps = node->vfd.device_caps; + + dev_dbg(pispbe->dev, "Caps for node %s: %x and %x (dev %x)\n", + NODE_NAME(node), cap->capabilities, cap->device_caps, + node->vfd.device_caps); ++ + return 0; + } + +@@ -1070,17 +995,19 @@ static int pispbe_node_g_fmt_vid_cap(str + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; + + if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { +- dev_err(pispbe->dev, ++ dev_dbg(pispbe->dev, + "Cannot get capture fmt for output node %s\n", + NODE_NAME(node)); + return -EINVAL; + } ++ + *f = node->format; + dev_dbg(pispbe->dev, "Get capture format for node %s\n", + NODE_NAME(node)); ++ + return 0; + } + +@@ -1088,17 +1015,19 @@ static int pispbe_node_g_fmt_vid_out(str + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; + + if (NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { +- dev_err(pispbe->dev, ++ dev_dbg(pispbe->dev, + "Cannot get capture fmt for output node %s\n", + NODE_NAME(node)); + return -EINVAL; + } ++ + *f = node->format; + dev_dbg(pispbe->dev, "Get output format for node %s\n", + NODE_NAME(node)); ++ + return 0; + } + +@@ -1106,98 +1035,42 @@ static int pispbe_node_g_fmt_meta_out(st + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; + + if (!NODE_IS_META(node) || NODE_IS_CAPTURE(node)) { +- dev_err(pispbe->dev, ++ dev_dbg(pispbe->dev, + "Cannot get capture fmt for meta output node %s\n", + NODE_NAME(node)); + return -EINVAL; + } +- *f = node->format; +- dev_dbg(pispbe->dev, "Get output format for meta node %s\n", +- NODE_NAME(node)); +- return 0; +-} + +-static int pispbe_node_g_fmt_meta_cap(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- +- if (!NODE_IS_META(node) || NODE_IS_OUTPUT(node)) { +- dev_err(pispbe->dev, +- "Cannot get capture fmt for meta output node %s\n", +- NODE_NAME(node)); +- return -EINVAL; +- } + *f = node->format; + dev_dbg(pispbe->dev, "Get output format for meta node %s\n", + NODE_NAME(node)); +- return 0; +-} +- +-static int verify_be_pix_format(const struct v4l2_format *f, +- struct pispbe_node *node) +-{ +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- unsigned int nplanes = f->fmt.pix_mp.num_planes; +- unsigned int i; +- +- if (f->fmt.pix_mp.width == 0 || f->fmt.pix_mp.height == 0) { +- dev_err(pispbe->dev, "Details incorrect for output node %s\n", +- NODE_NAME(node)); +- return -EINVAL; +- } +- +- if (nplanes == 0 || nplanes > MAX_PLANES) { +- dev_err(pispbe->dev, +- "Bad number of planes for output node %s, req =%d\n", +- NODE_NAME(node), nplanes); +- return -EINVAL; +- } +- +- for (i = 0; i < nplanes; i++) { +- const struct v4l2_plane_pix_format *p; +- +- p = &f->fmt.pix_mp.plane_fmt[i]; +- if (p->bytesperline == 0 || p->sizeimage == 0) { +- dev_err(pispbe->dev, +- "Invalid plane %d for output node %s\n", +- i, NODE_NAME(node)); +- return -EINVAL; +- } +- } + + return 0; + } + +-static const struct pisp_be_format *find_format(unsigned int fourcc) ++static const struct pisp_be_format *pispbe_find_fmt(unsigned int fourcc) + { +- const struct pisp_be_format *fmt; +- unsigned int i; +- +- for (i = 0; i < ARRAY_SIZE(supported_formats); i++) { +- fmt = &supported_formats[i]; +- if (fmt->fourcc == fourcc) +- return fmt; ++ for (unsigned int i = 0; i < ARRAY_SIZE(supported_formats); i++) { ++ if (supported_formats[i].fourcc == fourcc) ++ return &supported_formats[i]; + } + + return NULL; + } + +-static void set_plane_params(struct v4l2_format *f, +- const struct pisp_be_format *fmt) ++static void pispbe_set_plane_params(struct v4l2_format *f, ++ const struct pisp_be_format *fmt) + { + unsigned int nplanes = f->fmt.pix_mp.num_planes; + unsigned int total_plane_factor = 0; +- unsigned int i; + +- for (i = 0; i < MAX_PLANES; i++) ++ for (unsigned int i = 0; i < PISPBE_MAX_PLANES; i++) + total_plane_factor += fmt->plane_factor[i]; + +- for (i = 0; i < nplanes; i++) { ++ for (unsigned int i = 0; i < nplanes; i++) { + struct v4l2_plane_pix_format *p = &f->fmt.pix_mp.plane_fmt[i]; + unsigned int bpl, plane_size; + +@@ -1217,28 +1090,25 @@ static void set_plane_params(struct v4l2 + } + } + +-static int try_format(struct v4l2_format *f, struct pispbe_node *node) ++static void pispbe_try_format(struct v4l2_format *f, struct pispbe_node *node) + { +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; ++ u32 pixfmt = f->fmt.pix_mp.pixelformat; + const struct pisp_be_format *fmt; +- unsigned int i; + bool is_rgb; +- u32 pixfmt = f->fmt.pix_mp.pixelformat; + + dev_dbg(pispbe->dev, +- "%s: [%s] req %ux%u " V4L2_FOURCC_CONV ", planes %d\n", ++ "%s: [%s] req %ux%u %p4cc, planes %d\n", + __func__, NODE_NAME(node), f->fmt.pix_mp.width, +- f->fmt.pix_mp.height, V4L2_FOURCC_CONV_ARGS(pixfmt), ++ f->fmt.pix_mp.height, &pixfmt, + f->fmt.pix_mp.num_planes); + +- if (pixfmt == V4L2_PIX_FMT_RPI_BE) +- return verify_be_pix_format(f, node); +- +- fmt = find_format(pixfmt); ++ fmt = pispbe_find_fmt(pixfmt); + if (!fmt) { +- dev_dbg(pispbe->dev, "%s: [%s] Format not found, defaulting to YUV420\n", ++ dev_dbg(pispbe->dev, ++ "%s: [%s] Format not found, defaulting to YUV420\n", + __func__, NODE_NAME(node)); +- fmt = find_format(V4L2_PIX_FMT_YUV420); ++ fmt = pispbe_find_fmt(V4L2_PIX_FMT_YUV420); + } + + f->fmt.pix_mp.pixelformat = fmt->fourcc; +@@ -1254,7 +1124,8 @@ static int try_format(struct v4l2_format + * not supported. This also catches the case when the "default" + * colour space was requested (as that's never in the mask). + */ +- if (!(V4L2_COLORSPACE_MASK(f->fmt.pix_mp.colorspace) & fmt->colorspace_mask)) ++ if (!(V4L2_COLORSPACE_MASK(f->fmt.pix_mp.colorspace) & ++ fmt->colorspace_mask)) + f->fmt.pix_mp.colorspace = fmt->colorspace_default; + + /* In all cases, we only support the defaults for these: */ +@@ -1269,9 +1140,9 @@ static int try_format(struct v4l2_format + f->fmt.pix_mp.ycbcr_enc); + + /* Set plane size and bytes/line for each plane. */ +- set_plane_params(f, fmt); ++ pispbe_set_plane_params(f, fmt); + +- for (i = 0; i < f->fmt.pix_mp.num_planes; i++) { ++ for (unsigned int i = 0; i < f->fmt.pix_mp.num_planes; i++) { + dev_dbg(pispbe->dev, + "%s: [%s] calc plane %d, %ux%u, depth %u, bpl %u size %u\n", + __func__, NODE_NAME(node), i, f->fmt.pix_mp.width, +@@ -1279,27 +1150,22 @@ static int try_format(struct v4l2_format + f->fmt.pix_mp.plane_fmt[i].bytesperline, + f->fmt.pix_mp.plane_fmt[i].sizeimage); + } +- +- return 0; + } + + static int pispbe_node_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- int ret; ++ struct pispbe_dev *pispbe = node->pispbe; + + if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { +- dev_err(pispbe->dev, ++ dev_dbg(pispbe->dev, + "Cannot set capture fmt for output node %s\n", + NODE_NAME(node)); + return -EINVAL; + } + +- ret = try_format(f, node); +- if (ret < 0) +- return ret; ++ pispbe_try_format(f, node); + + return 0; + } +@@ -1308,19 +1174,16 @@ static int pispbe_node_try_fmt_vid_out(s + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- int ret; ++ struct pispbe_dev *pispbe = node->pispbe; + + if (!NODE_IS_OUTPUT(node) || NODE_IS_META(node)) { +- dev_err(pispbe->dev, ++ dev_dbg(pispbe->dev, + "Cannot set capture fmt for output node %s\n", + NODE_NAME(node)); + return -EINVAL; + } + +- ret = try_format(f, node); +- if (ret < 0) +- return ret; ++ pispbe_try_format(f, node); + + return 0; + } +@@ -1329,10 +1192,10 @@ static int pispbe_node_try_fmt_meta_out( + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; + + if (!NODE_IS_META(node) || NODE_IS_CAPTURE(node)) { +- dev_err(pispbe->dev, ++ dev_dbg(pispbe->dev, + "Cannot set capture fmt for meta output node %s\n", + NODE_NAME(node)); + return -EINVAL; +@@ -1344,43 +1207,26 @@ static int pispbe_node_try_fmt_meta_out( + return 0; + } + +-static int pispbe_node_try_fmt_meta_cap(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- +- if (!NODE_IS_META(node) || NODE_IS_OUTPUT(node)) { +- dev_err(pispbe->dev, +- "Cannot set capture fmt for meta output node %s\n", +- NODE_NAME(node)); +- return -EINVAL; +- } +- +- f->fmt.meta.dataformat = V4L2_PIX_FMT_RPI_BE; +- if (!f->fmt.meta.buffersize) +- f->fmt.meta.buffersize = BIT(20); +- +- return 0; +-} +- + static int pispbe_node_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- int ret = pispbe_node_try_fmt_vid_cap(file, priv, f); ++ struct pispbe_dev *pispbe = node->pispbe; ++ int ret; + ++ ret = pispbe_node_try_fmt_vid_cap(file, priv, f); + if (ret < 0) + return ret; + ++ if (vb2_is_busy(&node->queue)) ++ return -EBUSY; ++ + node->format = *f; +- node->pisp_format = find_format(f->fmt.pix_mp.pixelformat); ++ node->pisp_format = pispbe_find_fmt(f->fmt.pix_mp.pixelformat); ++ ++ dev_dbg(pispbe->dev, "Set capture format for node %s to %p4cc\n", ++ NODE_NAME(node), &f->fmt.pix_mp.pixelformat); + +- dev_dbg(pispbe->dev, +- "Set capture format for node %s to " V4L2_FOURCC_CONV "\n", +- NODE_NAME(node), +- V4L2_FOURCC_CONV_ARGS(f->fmt.pix_mp.pixelformat)); + return 0; + } + +@@ -1388,19 +1234,22 @@ static int pispbe_node_s_fmt_vid_out(str + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- int ret = pispbe_node_try_fmt_vid_out(file, priv, f); ++ struct pispbe_dev *pispbe = node->pispbe; ++ int ret; + ++ ret = pispbe_node_try_fmt_vid_out(file, priv, f); + if (ret < 0) + return ret; + ++ if (vb2_is_busy(&node->queue)) ++ return -EBUSY; ++ + node->format = *f; +- node->pisp_format = find_format(f->fmt.pix_mp.pixelformat); ++ node->pisp_format = pispbe_find_fmt(f->fmt.pix_mp.pixelformat); ++ ++ dev_dbg(pispbe->dev, "Set output format for node %s to %p4cc\n", ++ NODE_NAME(node), &f->fmt.pix_mp.pixelformat); + +- dev_dbg(pispbe->dev, +- "Set output format for node %s to " V4L2_FOURCC_CONV "\n", +- NODE_NAME(node), +- V4L2_FOURCC_CONV_ARGS(f->fmt.pix_mp.pixelformat)); + return 0; + } + +@@ -1408,39 +1257,22 @@ static int pispbe_node_s_fmt_meta_out(st + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- int ret = pispbe_node_try_fmt_meta_out(file, priv, f); ++ struct pispbe_dev *pispbe = node->pispbe; ++ int ret; + ++ ret = pispbe_node_try_fmt_meta_out(file, priv, f); + if (ret < 0) + return ret; + ++ if (vb2_is_busy(&node->queue)) ++ return -EBUSY; ++ + node->format = *f; + node->pisp_format = &meta_out_supported_formats[0]; + +- dev_dbg(pispbe->dev, +- "Set output format for meta node %s to " V4L2_FOURCC_CONV "\n", +- NODE_NAME(node), +- V4L2_FOURCC_CONV_ARGS(f->fmt.meta.dataformat)); +- return 0; +-} +- +-static int pispbe_node_s_fmt_meta_cap(struct file *file, void *priv, +- struct v4l2_format *f) +-{ +- struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- int ret = pispbe_node_try_fmt_meta_cap(file, priv, f); +- +- if (ret < 0) +- return ret; +- +- node->format = *f; +- node->pisp_format = find_format(f->fmt.meta.dataformat); ++ dev_dbg(pispbe->dev, "Set output format for meta node %s to %p4cc\n", ++ NODE_NAME(node), &f->fmt.meta.dataformat); + +- dev_dbg(pispbe->dev, +- "Set capture format for meta node %s to " V4L2_FOURCC_CONV "\n", +- NODE_NAME(node), +- V4L2_FOURCC_CONV_ARGS(f->fmt.meta.dataformat)); + return 0; + } + +@@ -1456,10 +1288,7 @@ static int pispbe_node_enum_fmt(struct f + if (f->index) + return -EINVAL; + +- if (NODE_IS_OUTPUT(node)) +- f->pixelformat = V4L2_META_FMT_RPI_BE_CFG; +- else +- f->pixelformat = V4L2_PIX_FMT_RPI_BE; ++ f->pixelformat = V4L2_META_FMT_RPI_BE_CFG; + f->flags = 0; + return 0; + } +@@ -1477,13 +1306,13 @@ static int pispbe_enum_framesizes(struct + struct v4l2_frmsizeenum *fsize) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; ++ struct pispbe_dev *pispbe = node->pispbe; + + if (NODE_IS_META(node) || fsize->index) + return -EINVAL; + +- if (!find_format(fsize->pixel_format)) { +- dev_err(pispbe->dev, "Invalid pixel code: %x\n", ++ if (!pispbe_find_fmt(fsize->pixel_format)) { ++ dev_dbg(pispbe->dev, "Invalid pixel code: %x\n", + fsize->pixel_format); + return -EINVAL; + } +@@ -1500,49 +1329,19 @@ static int pispbe_enum_framesizes(struct + return 0; + } + +-static int pispbe_node_streamon(struct file *file, void *priv, +- enum v4l2_buf_type type) +-{ +- struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->node_group->pispbe; +- +- /* Do we need a node->stream_lock mutex? */ +- +- dev_dbg(pispbe->dev, "Stream on for node %s\n", NODE_NAME(node)); +- +- /* Do we care about the type? Each node has only one queue. */ +- +- INIT_LIST_HEAD(&node->ready_queue); +- +- /* locking should be handled by the queue->lock? */ +- return vb2_streamon(&node->queue, type); +-} +- +-static int pispbe_node_streamoff(struct file *file, void *priv, +- enum v4l2_buf_type type) +-{ +- struct pispbe_node *node = video_drvdata(file); +- +- return vb2_streamoff(&node->queue, type); +-} +- + static const struct v4l2_ioctl_ops pispbe_node_ioctl_ops = { + .vidioc_querycap = pispbe_node_querycap, + .vidioc_g_fmt_vid_cap_mplane = pispbe_node_g_fmt_vid_cap, + .vidioc_g_fmt_vid_out_mplane = pispbe_node_g_fmt_vid_out, + .vidioc_g_fmt_meta_out = pispbe_node_g_fmt_meta_out, +- .vidioc_g_fmt_meta_cap = pispbe_node_g_fmt_meta_cap, + .vidioc_try_fmt_vid_cap_mplane = pispbe_node_try_fmt_vid_cap, + .vidioc_try_fmt_vid_out_mplane = pispbe_node_try_fmt_vid_out, + .vidioc_try_fmt_meta_out = pispbe_node_try_fmt_meta_out, +- .vidioc_try_fmt_meta_cap = pispbe_node_try_fmt_meta_cap, + .vidioc_s_fmt_vid_cap_mplane = pispbe_node_s_fmt_vid_cap, + .vidioc_s_fmt_vid_out_mplane = pispbe_node_s_fmt_vid_out, + .vidioc_s_fmt_meta_out = pispbe_node_s_fmt_meta_out, +- .vidioc_s_fmt_meta_cap = pispbe_node_s_fmt_meta_cap, + .vidioc_enum_fmt_vid_cap = pispbe_node_enum_fmt, + .vidioc_enum_fmt_vid_out = pispbe_node_enum_fmt, +- .vidioc_enum_fmt_meta_cap = pispbe_node_enum_fmt, + .vidioc_enum_fmt_meta_out = pispbe_node_enum_fmt, + .vidioc_enum_framesizes = pispbe_enum_framesizes, + .vidioc_create_bufs = vb2_ioctl_create_bufs, +@@ -1552,8 +1351,8 @@ static const struct v4l2_ioctl_ops pispb + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, + .vidioc_reqbufs = vb2_ioctl_reqbufs, +- .vidioc_streamon = pispbe_node_streamon, +- .vidioc_streamoff = pispbe_node_streamoff, ++ .vidioc_streamon = vb2_ioctl_streamon, ++ .vidioc_streamoff = vb2_ioctl_streamoff, + }; + + static const struct video_device pispbe_videodev = { +@@ -1565,7 +1364,7 @@ static const struct video_device pispbe_ + .release = video_device_release_empty, + }; + +-static void node_set_default_format(struct pispbe_node *node) ++static void pispbe_node_def_fmt(struct pispbe_node *node) + { + if (NODE_IS_META(node) && NODE_IS_OUTPUT(node)) { + /* Config node */ +@@ -1574,44 +1373,35 @@ static void node_set_default_format(stru + f->fmt.meta.dataformat = V4L2_META_FMT_RPI_BE_CFG; + f->fmt.meta.buffersize = sizeof(struct pisp_be_tiles_config); + f->type = node->buf_type; +- } else if (NODE_IS_META(node) && NODE_IS_CAPTURE(node)) { +- /* HOG output node */ +- struct v4l2_format *f = &node->format; +- +- f->fmt.meta.dataformat = V4L2_PIX_FMT_RPI_BE; +- f->fmt.meta.buffersize = BIT(20); +- f->type = node->buf_type; + } else { +- struct v4l2_format f = {0}; +- +- f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420; +- f.fmt.pix_mp.width = 1920; +- f.fmt.pix_mp.height = 1080; +- f.type = node->buf_type; +- try_format(&f, node); ++ struct v4l2_format f = { ++ .fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420, ++ .fmt.pix_mp.width = 1920, ++ .fmt.pix_mp.height = 1080, ++ .type = node->buf_type, ++ }; ++ pispbe_try_format(&f, node); + node->format = f; + } + +- node->pisp_format = find_format(node->format.fmt.pix_mp.pixelformat); ++ node->pisp_format = pispbe_find_fmt(node->format.fmt.pix_mp.pixelformat); + } + + /* + * Initialise a struct pispbe_node and register it as /dev/video + * to represent one of the PiSP Back End's input or output streams. + */ +-static int +-pispbe_init_node(struct pispbe_node_group *node_group, unsigned int id) ++static int pispbe_init_node(struct pispbe_dev *pispbe, unsigned int id) + { + bool output = NODE_DESC_IS_OUTPUT(&node_desc[id]); +- struct pispbe_node *node = &node_group->node[id]; +- struct pispbe_dev *pispbe = node_group->pispbe; ++ struct pispbe_node *node = &pispbe->node[id]; + struct media_entity *entity = &node->vfd.entity; + struct video_device *vdev = &node->vfd; + struct vb2_queue *q = &node->queue; + int ret; + + node->id = id; +- node->node_group = node_group; ++ node->pispbe = pispbe; + node->buf_type = node_desc[id].buf_type; + + mutex_init(&node->node_lock); +@@ -1620,7 +1410,7 @@ pispbe_init_node(struct pispbe_node_grou + spin_lock_init(&node->ready_lock); + + node->format.type = node->buf_type; +- node_set_default_format(node); ++ pispbe_node_def_fmt(node); + + q->type = node->buf_type; + q->io_modes = VB2_MMAP | VB2_DMABUF; +@@ -1629,19 +1419,19 @@ pispbe_init_node(struct pispbe_node_grou + q->ops = &pispbe_node_queue_ops; + q->buf_struct_size = sizeof(struct pispbe_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; +- q->dev = node->node_group->pispbe->dev; ++ q->dev = pispbe->dev; + /* get V4L2 to handle node->queue locking */ + q->lock = &node->queue_lock; + + ret = vb2_queue_init(q); + if (ret < 0) { + dev_err(pispbe->dev, "vb2_queue_init failed\n"); +- return ret; ++ goto err_mutex_destroy; + } + + *vdev = pispbe_videodev; /* default initialization */ + strscpy(vdev->name, node_desc[id].ent_name, sizeof(vdev->name)); +- vdev->v4l2_dev = &node_group->v4l2_dev; ++ vdev->v4l2_dev = &pispbe->v4l2_dev; + vdev->vfl_dir = output ? VFL_DIR_TX : VFL_DIR_RX; + /* get V4L2 to serialise our ioctls */ + vdev->lock = &node->node_lock; +@@ -1657,8 +1447,7 @@ pispbe_init_node(struct pispbe_node_grou + goto err_unregister_queue; + } + +- ret = video_register_device(vdev, VFL_TYPE_VIDEO, +- PISPBE_VIDEO_NODE_OFFSET); ++ ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); + if (ret) { + dev_err(pispbe->dev, + "Failed to register video %s device node\n", +@@ -1668,25 +1457,28 @@ pispbe_init_node(struct pispbe_node_grou + video_set_drvdata(vdev, node); + + if (output) +- ret = media_create_pad_link(entity, 0, &node_group->sd.entity, ++ ret = media_create_pad_link(entity, 0, &pispbe->sd.entity, + id, MEDIA_LNK_FL_IMMUTABLE | + MEDIA_LNK_FL_ENABLED); + else +- ret = media_create_pad_link(&node_group->sd.entity, id, entity, ++ ret = media_create_pad_link(&pispbe->sd.entity, id, entity, + 0, MEDIA_LNK_FL_IMMUTABLE | + MEDIA_LNK_FL_ENABLED); + if (ret) + goto err_unregister_video_dev; + +- dev_info(pispbe->dev, +- "%s device node registered as /dev/video%d\n", +- NODE_NAME(node), node->vfd.num); ++ dev_dbg(pispbe->dev, "%s device node registered as /dev/video%d\n", ++ NODE_NAME(node), node->vfd.num); ++ + return 0; + + err_unregister_video_dev: + video_unregister_device(&node->vfd); + err_unregister_queue: + vb2_queue_release(&node->queue); ++err_mutex_destroy: ++ mutex_destroy(&node->node_lock); ++ mutex_destroy(&node->queue_lock); + return ret; + } + +@@ -1698,11 +1490,9 @@ static const struct v4l2_subdev_ops pisp + .pad = &pispbe_pad_ops, + }; + +-static int pispbe_init_subdev(struct pispbe_node_group *node_group) ++static int pispbe_init_subdev(struct pispbe_dev *pispbe) + { +- struct pispbe_dev *pispbe = node_group->pispbe; +- struct v4l2_subdev *sd = &node_group->sd; +- unsigned int i; ++ struct v4l2_subdev *sd = &pispbe->sd; + int ret; + + v4l2_subdev_init(sd, &pispbe_sd_ops); +@@ -1711,17 +1501,17 @@ static int pispbe_init_subdev(struct pis + sd->dev = pispbe->dev; + strscpy(sd->name, PISPBE_NAME, sizeof(sd->name)); + +- for (i = 0; i < PISPBE_NUM_NODES; i++) +- node_group->pad[i].flags = ++ for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) ++ pispbe->pad[i].flags = + NODE_DESC_IS_OUTPUT(&node_desc[i]) ? + MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&sd->entity, PISPBE_NUM_NODES, +- node_group->pad); ++ pispbe->pad); + if (ret) + goto error; + +- ret = v4l2_device_register_subdev(&node_group->v4l2_dev, sd); ++ ret = v4l2_device_register_subdev(&pispbe->v4l2_dev, sd); + if (ret) + goto error; + +@@ -1732,45 +1522,36 @@ error: + return ret; + } + +-static int pispbe_init_group(struct pispbe_dev *pispbe, unsigned int id) ++static int pispbe_init_devices(struct pispbe_dev *pispbe) + { +- struct pispbe_node_group *node_group = &pispbe->node_group[id]; + struct v4l2_device *v4l2_dev; + struct media_device *mdev; +- unsigned int num_registered = 0; ++ unsigned int num_regist; + int ret; + +- node_group->id = id; +- node_group->pispbe = pispbe; +- node_group->streaming_map = 0; +- +- dev_info(pispbe->dev, "Register nodes for group %u\n", id); +- + /* Register v4l2_device and media_device */ +- mdev = &node_group->mdev; +- mdev->hw_revision = node_group->pispbe->hw_version; +- mdev->dev = node_group->pispbe->dev; ++ mdev = &pispbe->mdev; ++ mdev->hw_revision = pispbe->hw_version; ++ mdev->dev = pispbe->dev; + strscpy(mdev->model, PISPBE_NAME, sizeof(mdev->model)); +- snprintf(mdev->bus_info, sizeof(mdev->bus_info), +- "platform:%s", dev_name(node_group->pispbe->dev)); + media_device_init(mdev); + +- v4l2_dev = &node_group->v4l2_dev; +- v4l2_dev->mdev = &node_group->mdev; ++ v4l2_dev = &pispbe->v4l2_dev; ++ v4l2_dev->mdev = &pispbe->mdev; + strscpy(v4l2_dev->name, PISPBE_NAME, sizeof(v4l2_dev->name)); + +- ret = v4l2_device_register(pispbe->dev, &node_group->v4l2_dev); ++ ret = v4l2_device_register(pispbe->dev, v4l2_dev); + if (ret) + goto err_media_dev_cleanup; + + /* Register the PISPBE subdevice. */ +- ret = pispbe_init_subdev(node_group); ++ ret = pispbe_init_subdev(pispbe); + if (ret) + goto err_unregister_v4l2; + + /* Create device video nodes */ +- for (; num_registered < PISPBE_NUM_NODES; num_registered++) { +- ret = pispbe_init_node(node_group, num_registered); ++ for (num_regist = 0; num_regist < PISPBE_NUM_NODES; num_regist++) { ++ ret = pispbe_init_node(pispbe, num_regist); + if (ret) + goto err_unregister_nodes; + } +@@ -1779,12 +1560,12 @@ static int pispbe_init_group(struct pisp + if (ret) + goto err_unregister_nodes; + +- node_group->config = ++ pispbe->config = + dma_alloc_coherent(pispbe->dev, + sizeof(struct pisp_be_tiles_config) * + PISP_BE_NUM_CONFIG_BUFFERS, +- &node_group->config_dma_addr, GFP_KERNEL); +- if (!node_group->config) { ++ &pispbe->config_dma_addr, GFP_KERNEL); ++ if (!pispbe->config) { + dev_err(pispbe->dev, "Unable to allocate cached config buffers.\n"); + ret = -ENOMEM; + goto err_unregister_mdev; +@@ -1795,12 +1576,12 @@ static int pispbe_init_group(struct pisp + err_unregister_mdev: + media_device_unregister(mdev); + err_unregister_nodes: +- while (num_registered-- > 0) { +- video_unregister_device(&node_group->node[num_registered].vfd); +- vb2_queue_release(&node_group->node[num_registered].queue); ++ while (num_regist-- > 0) { ++ video_unregister_device(&pispbe->node[num_regist].vfd); ++ vb2_queue_release(&pispbe->node[num_regist].queue); + } +- v4l2_device_unregister_subdev(&node_group->sd); +- media_entity_cleanup(&node_group->sd.entity); ++ v4l2_device_unregister_subdev(&pispbe->sd); ++ media_entity_cleanup(&pispbe->sd.entity); + err_unregister_v4l2: + v4l2_device_unregister(v4l2_dev); + err_media_dev_cleanup: +@@ -1808,32 +1589,31 @@ err_media_dev_cleanup: + return ret; + } + +-static void pispbe_destroy_node_group(struct pispbe_node_group *node_group) ++static void pispbe_destroy_devices(struct pispbe_dev *pispbe) + { +- struct pispbe_dev *pispbe = node_group->pispbe; +- int i; +- +- if (node_group->config) { +- dma_free_coherent(node_group->pispbe->dev, ++ if (pispbe->config) { ++ dma_free_coherent(pispbe->dev, + sizeof(struct pisp_be_tiles_config) * + PISP_BE_NUM_CONFIG_BUFFERS, +- node_group->config, +- node_group->config_dma_addr); ++ pispbe->config, ++ pispbe->config_dma_addr); + } + +- dev_info(pispbe->dev, "Unregister from media controller\n"); ++ dev_dbg(pispbe->dev, "Unregister from media controller\n"); + +- v4l2_device_unregister_subdev(&node_group->sd); +- media_entity_cleanup(&node_group->sd.entity); +- media_device_unregister(&node_group->mdev); ++ v4l2_device_unregister_subdev(&pispbe->sd); ++ media_entity_cleanup(&pispbe->sd.entity); ++ media_device_unregister(&pispbe->mdev); + +- for (i = PISPBE_NUM_NODES - 1; i >= 0; i--) { +- video_unregister_device(&node_group->node[i].vfd); +- vb2_queue_release(&node_group->node[i].queue); ++ for (int i = PISPBE_NUM_NODES - 1; i >= 0; i--) { ++ video_unregister_device(&pispbe->node[i].vfd); ++ vb2_queue_release(&pispbe->node[i].queue); ++ mutex_destroy(&pispbe->node[i].node_lock); ++ mutex_destroy(&pispbe->node[i].queue_lock); + } + +- media_device_cleanup(&node_group->mdev); +- v4l2_device_unregister(&node_group->v4l2_dev); ++ media_device_cleanup(&pispbe->mdev); ++ v4l2_device_unregister(&pispbe->v4l2_dev); + } + + static int pispbe_runtime_suspend(struct device *dev) +@@ -1862,13 +1642,48 @@ static int pispbe_runtime_resume(struct + return 0; + } + +-/* +- * Probe the ISP-BE hardware block, as a single platform device. +- * This will instantiate multiple "node groups" each with many device nodes. +- */ ++static int pispbe_hw_init(struct pispbe_dev *pispbe) ++{ ++ u32 u; ++ ++ /* Check the HW is present and has a known version */ ++ u = pispbe_rd(pispbe, PISP_BE_VERSION_REG); ++ dev_dbg(pispbe->dev, "pispbe_probe: HW version: 0x%08x", u); ++ pispbe->hw_version = u; ++ if ((u & ~PISP_BE_VERSION_MINOR_BITS) != PISP_BE_VERSION_2712) ++ return -ENODEV; ++ ++ /* Clear leftover interrupts */ ++ pispbe_wr(pispbe, PISP_BE_INTERRUPT_STATUS_REG, 0xFFFFFFFFu); ++ u = pispbe_rd(pispbe, PISP_BE_BATCH_STATUS_REG); ++ dev_dbg(pispbe->dev, "pispbe_probe: BatchStatus: 0x%08x", u); ++ ++ pispbe->done = (uint8_t)u; ++ pispbe->started = (uint8_t)(u >> 8); ++ u = pispbe_rd(pispbe, PISP_BE_STATUS_REG); ++ dev_dbg(pispbe->dev, "pispbe_probe: Status: 0x%08x", u); ++ ++ if (u != 0 || pispbe->done != pispbe->started) { ++ dev_err(pispbe->dev, "pispbe_probe: HW is stuck or busy\n"); ++ return -EBUSY; ++ } ++ ++ /* ++ * AXI QOS=0, CACHE=4'b0010, PROT=3'b011 ++ * Also set "chicken bits" 22:20 which enable sub-64-byte bursts ++ * and AXI AWID/BID variability (on versions which support this). ++ */ ++ pispbe_wr(pispbe, PISP_BE_AXI_REG, 0x32703200u); ++ ++ /* Enable both interrupt flags */ ++ pispbe_wr(pispbe, PISP_BE_INTERRUPT_EN_REG, 0x00000003u); ++ ++ return 0; ++} ++ ++/* Probe the ISP-BE hardware block, as a single platform device. */ + static int pispbe_probe(struct platform_device *pdev) + { +- unsigned int num_groups = 0; + struct pispbe_dev *pispbe; + int ret; + +@@ -1913,55 +1728,43 @@ static int pispbe_probe(struct platform_ + pm_runtime_use_autosuspend(pispbe->dev); + pm_runtime_enable(pispbe->dev); + +- ret = pm_runtime_resume_and_get(pispbe->dev); ++ ret = pispbe_runtime_resume(pispbe->dev); + if (ret) + goto pm_runtime_disable_err; + +- pispbe->hw_busy = 0; ++ pispbe->hw_busy = false; + spin_lock_init(&pispbe->hw_lock); +- ret = hw_init(pispbe); ++ ret = pispbe_hw_init(pispbe); + if (ret) +- goto pm_runtime_put_err; ++ goto pm_runtime_suspend_err; + +- /* +- * Initialise and register devices for each node_group, including media +- * device +- */ +- for (num_groups = 0; +- num_groups < PISPBE_NUM_NODE_GROUPS; +- num_groups++) { +- ret = pispbe_init_group(pispbe, num_groups); +- if (ret) +- goto disable_nodes_err; +- } ++ ret = pispbe_init_devices(pispbe); ++ if (ret) ++ goto disable_devs_err; + + pm_runtime_mark_last_busy(pispbe->dev); + pm_runtime_put_autosuspend(pispbe->dev); + + return 0; + +-disable_nodes_err: +- while (num_groups-- > 0) +- pispbe_destroy_node_group(&pispbe->node_group[num_groups]); +-pm_runtime_put_err: +- pm_runtime_put(pispbe->dev); ++disable_devs_err: ++ pispbe_destroy_devices(pispbe); ++pm_runtime_suspend_err: ++ pispbe_runtime_suspend(pispbe->dev); + pm_runtime_disable_err: + pm_runtime_dont_use_autosuspend(pispbe->dev); + pm_runtime_disable(pispbe->dev); + +- dev_err(&pdev->dev, "%s: returning %d", __func__, ret); +- + return ret; + } + + static int pispbe_remove(struct platform_device *pdev) + { + struct pispbe_dev *pispbe = platform_get_drvdata(pdev); +- int i; + +- for (i = PISPBE_NUM_NODE_GROUPS - 1; i >= 0; i--) +- pispbe_destroy_node_group(&pispbe->node_group[i]); ++ pispbe_destroy_devices(pispbe); + ++ pispbe_runtime_suspend(pispbe->dev); + pm_runtime_dont_use_autosuspend(pispbe->dev); + pm_runtime_disable(pispbe->dev); + +@@ -1991,3 +1794,8 @@ static struct platform_driver pispbe_pdr + }; + + module_platform_driver(pispbe_pdrv); ++ ++MODULE_DESCRIPTION("PiSP Back End driver"); ++MODULE_AUTHOR("David Plowman "); ++MODULE_AUTHOR("Nick Hollinghurst "); ++MODULE_LICENSE("GPL"); +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be_config.h ++++ /dev/null +@@ -1,533 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +-/* +- * PiSP Back End configuration definitions. +- * +- * Copyright (C) 2021 - Raspberry Pi Ltd +- * +- */ +-#ifndef _PISP_BE_CONFIG_H_ +-#define _PISP_BE_CONFIG_H_ +- +-#include +- +-#include +- +-/* byte alignment for inputs */ +-#define PISP_BACK_END_INPUT_ALIGN 4u +-/* alignment for compressed inputs */ +-#define PISP_BACK_END_COMPRESSED_ALIGN 8u +-/* minimum required byte alignment for outputs */ +-#define PISP_BACK_END_OUTPUT_MIN_ALIGN 16u +-/* preferred byte alignment for outputs */ +-#define PISP_BACK_END_OUTPUT_MAX_ALIGN 64u +- +-/* minimum allowed tile width anywhere in the pipeline */ +-#define PISP_BACK_END_MIN_TILE_WIDTH 16u +-/* minimum allowed tile width anywhere in the pipeline */ +-#define PISP_BACK_END_MIN_TILE_HEIGHT 16u +- +-#define PISP_BACK_END_NUM_OUTPUTS 2 +-#define PISP_BACK_END_HOG_OUTPUT 1 +- +-#define PISP_BACK_END_NUM_TILES 64 +- +-enum pisp_be_bayer_enable { +- PISP_BE_BAYER_ENABLE_INPUT = 0x000001, +- PISP_BE_BAYER_ENABLE_DECOMPRESS = 0x000002, +- PISP_BE_BAYER_ENABLE_DPC = 0x000004, +- PISP_BE_BAYER_ENABLE_GEQ = 0x000008, +- PISP_BE_BAYER_ENABLE_TDN_INPUT = 0x000010, +- PISP_BE_BAYER_ENABLE_TDN_DECOMPRESS = 0x000020, +- PISP_BE_BAYER_ENABLE_TDN = 0x000040, +- PISP_BE_BAYER_ENABLE_TDN_COMPRESS = 0x000080, +- PISP_BE_BAYER_ENABLE_TDN_OUTPUT = 0x000100, +- PISP_BE_BAYER_ENABLE_SDN = 0x000200, +- PISP_BE_BAYER_ENABLE_BLC = 0x000400, +- PISP_BE_BAYER_ENABLE_STITCH_INPUT = 0x000800, +- PISP_BE_BAYER_ENABLE_STITCH_DECOMPRESS = 0x001000, +- PISP_BE_BAYER_ENABLE_STITCH = 0x002000, +- PISP_BE_BAYER_ENABLE_STITCH_COMPRESS = 0x004000, +- PISP_BE_BAYER_ENABLE_STITCH_OUTPUT = 0x008000, +- PISP_BE_BAYER_ENABLE_WBG = 0x010000, +- PISP_BE_BAYER_ENABLE_CDN = 0x020000, +- PISP_BE_BAYER_ENABLE_LSC = 0x040000, +- PISP_BE_BAYER_ENABLE_TONEMAP = 0x080000, +- PISP_BE_BAYER_ENABLE_CAC = 0x100000, +- PISP_BE_BAYER_ENABLE_DEBIN = 0x200000, +- PISP_BE_BAYER_ENABLE_DEMOSAIC = 0x400000, +-}; +- +-enum pisp_be_rgb_enable { +- PISP_BE_RGB_ENABLE_INPUT = 0x000001, +- PISP_BE_RGB_ENABLE_CCM = 0x000002, +- PISP_BE_RGB_ENABLE_SAT_CONTROL = 0x000004, +- PISP_BE_RGB_ENABLE_YCBCR = 0x000008, +- PISP_BE_RGB_ENABLE_FALSE_COLOUR = 0x000010, +- PISP_BE_RGB_ENABLE_SHARPEN = 0x000020, +- /* Preferred colours would occupy 0x000040 */ +- PISP_BE_RGB_ENABLE_YCBCR_INVERSE = 0x000080, +- PISP_BE_RGB_ENABLE_GAMMA = 0x000100, +- PISP_BE_RGB_ENABLE_CSC0 = 0x000200, +- PISP_BE_RGB_ENABLE_CSC1 = 0x000400, +- PISP_BE_RGB_ENABLE_DOWNSCALE0 = 0x001000, +- PISP_BE_RGB_ENABLE_DOWNSCALE1 = 0x002000, +- PISP_BE_RGB_ENABLE_RESAMPLE0 = 0x008000, +- PISP_BE_RGB_ENABLE_RESAMPLE1 = 0x010000, +- PISP_BE_RGB_ENABLE_OUTPUT0 = 0x040000, +- PISP_BE_RGB_ENABLE_OUTPUT1 = 0x080000, +- PISP_BE_RGB_ENABLE_HOG = 0x200000 +-}; +- +-#define PISP_BE_RGB_ENABLE_CSC(i) (PISP_BE_RGB_ENABLE_CSC0 << (i)) +-#define PISP_BE_RGB_ENABLE_DOWNSCALE(i) (PISP_BE_RGB_ENABLE_DOWNSCALE0 << (i)) +-#define PISP_BE_RGB_ENABLE_RESAMPLE(i) (PISP_BE_RGB_ENABLE_RESAMPLE0 << (i)) +-#define PISP_BE_RGB_ENABLE_OUTPUT(i) (PISP_BE_RGB_ENABLE_OUTPUT0 << (i)) +- +-/* +- * We use the enable flags to show when blocks are "dirty", but we need some +- * extra ones too. +- */ +-enum pisp_be_dirty { +- PISP_BE_DIRTY_GLOBAL = 0x0001, +- PISP_BE_DIRTY_SH_FC_COMBINE = 0x0002, +- PISP_BE_DIRTY_CROP = 0x0004 +-}; +- +-struct pisp_be_global_config { +- u32 bayer_enables; +- u32 rgb_enables; +- u8 bayer_order; +- u8 pad[3]; +-}; +- +-struct pisp_be_input_buffer_config { +- /* low 32 bits followed by high 32 bits (for each of up to 3 planes) */ +- u32 addr[3][2]; +-}; +- +-struct pisp_be_dpc_config { +- u8 coeff_level; +- u8 coeff_range; +- u8 pad; +-#define PISP_BE_DPC_FLAG_FOLDBACK 1 +- u8 flags; +-}; +- +-struct pisp_be_geq_config { +- u16 offset; +-#define PISP_BE_GEQ_SHARPER BIT(15) +-#define PISP_BE_GEQ_SLOPE ((1 << 10) - 1) +- /* top bit is the "sharper" flag, slope value is bottom 10 bits */ +- u16 slope_sharper; +- u16 min; +- u16 max; +-}; +- +-struct pisp_be_tdn_input_buffer_config { +- /* low 32 bits followed by high 32 bits */ +- u32 addr[2]; +-}; +- +-struct pisp_be_tdn_config { +- u16 black_level; +- u16 ratio; +- u16 noise_constant; +- u16 noise_slope; +- u16 threshold; +- u8 reset; +- u8 pad; +-}; +- +-struct pisp_be_tdn_output_buffer_config { +- /* low 32 bits followed by high 32 bits */ +- u32 addr[2]; +-}; +- +-struct pisp_be_sdn_config { +- u16 black_level; +- u8 leakage; +- u8 pad; +- u16 noise_constant; +- u16 noise_slope; +- u16 noise_constant2; +- u16 noise_slope2; +-}; +- +-struct pisp_be_stitch_input_buffer_config { +- /* low 32 bits followed by high 32 bits */ +- u32 addr[2]; +-}; +- +-#define PISP_BE_STITCH_STREAMING_LONG 0x8000 +-#define PISP_BE_STITCH_EXPOSURE_RATIO_MASK 0x7fff +- +-struct pisp_be_stitch_config { +- u16 threshold_lo; +- u8 threshold_diff_power; +- u8 pad; +- +- /* top bit indicates whether streaming input is the long exposure */ +- u16 exposure_ratio; +- +- u8 motion_threshold_256; +- u8 motion_threshold_recip; +-}; +- +-struct pisp_be_stitch_output_buffer_config { +- /* low 32 bits followed by high 32 bits */ +- u32 addr[2]; +-}; +- +-struct pisp_be_cdn_config { +- u16 thresh; +- u8 iir_strength; +- u8 g_adjust; +-}; +- +-#define PISP_BE_LSC_LOG_GRID_SIZE 5 +-#define PISP_BE_LSC_GRID_SIZE (1 << PISP_BE_LSC_LOG_GRID_SIZE) +-#define PISP_BE_LSC_STEP_PRECISION 18 +- +-struct pisp_be_lsc_config { +- /* (1<<18) / grid_cell_width */ +- u16 grid_step_x; +- /* (1<<18) / grid_cell_height */ +- u16 grid_step_y; +- /* RGB gains jointly encoded in 32 bits */ +- u32 lut_packed[PISP_BE_LSC_GRID_SIZE + 1] +- [PISP_BE_LSC_GRID_SIZE + 1]; +-}; +- +-struct pisp_be_lsc_extra { +- u16 offset_x; +- u16 offset_y; +-}; +- +-#define PISP_BE_CAC_LOG_GRID_SIZE 3 +-#define PISP_BE_CAC_GRID_SIZE (1 << PISP_BE_CAC_LOG_GRID_SIZE) +-#define PISP_BE_CAC_STEP_PRECISION 20 +- +-struct pisp_be_cac_config { +- /* (1<<20) / grid_cell_width */ +- u16 grid_step_x; +- /* (1<<20) / grid_cell_height */ +- u16 grid_step_y; +- /* [gridy][gridx][rb][xy] */ +- s8 lut[PISP_BE_CAC_GRID_SIZE + 1][PISP_BE_CAC_GRID_SIZE + 1][2][2]; +-}; +- +-struct pisp_be_cac_extra { +- u16 offset_x; +- u16 offset_y; +-}; +- +-#define PISP_BE_DEBIN_NUM_COEFFS 4 +- +-struct pisp_be_debin_config { +- s8 coeffs[PISP_BE_DEBIN_NUM_COEFFS]; +- s8 h_enable; +- s8 v_enable; +- s8 pad[2]; +-}; +- +-#define PISP_BE_TONEMAP_LUT_SIZE 64 +- +-struct pisp_be_tonemap_config { +- u16 detail_constant; +- u16 detail_slope; +- u16 iir_strength; +- u16 strength; +- u32 lut[PISP_BE_TONEMAP_LUT_SIZE]; +-}; +- +-struct pisp_be_demosaic_config { +- u8 sharper; +- u8 fc_mode; +- u8 pad[2]; +-}; +- +-struct pisp_be_ccm_config { +- s16 coeffs[9]; +- u8 pad[2]; +- s32 offsets[3]; +-}; +- +-struct pisp_be_sat_control_config { +- u8 shift_r; +- u8 shift_g; +- u8 shift_b; +- u8 pad; +-}; +- +-struct pisp_be_false_colour_config { +- u8 distance; +- u8 pad[3]; +-}; +- +-#define PISP_BE_SHARPEN_SIZE 5 +-#define PISP_BE_SHARPEN_FUNC_NUM_POINTS 9 +- +-struct pisp_be_sharpen_config { +- s8 kernel0[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; +- s8 pad0[3]; +- s8 kernel1[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; +- s8 pad1[3]; +- s8 kernel2[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; +- s8 pad2[3]; +- s8 kernel3[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; +- s8 pad3[3]; +- s8 kernel4[PISP_BE_SHARPEN_SIZE * PISP_BE_SHARPEN_SIZE]; +- s8 pad4[3]; +- u16 threshold_offset0; +- u16 threshold_slope0; +- u16 scale0; +- u16 pad5; +- u16 threshold_offset1; +- u16 threshold_slope1; +- u16 scale1; +- u16 pad6; +- u16 threshold_offset2; +- u16 threshold_slope2; +- u16 scale2; +- u16 pad7; +- u16 threshold_offset3; +- u16 threshold_slope3; +- u16 scale3; +- u16 pad8; +- u16 threshold_offset4; +- u16 threshold_slope4; +- u16 scale4; +- u16 pad9; +- u16 positive_strength; +- u16 positive_pre_limit; +- u16 positive_func[PISP_BE_SHARPEN_FUNC_NUM_POINTS]; +- u16 positive_limit; +- u16 negative_strength; +- u16 negative_pre_limit; +- u16 negative_func[PISP_BE_SHARPEN_FUNC_NUM_POINTS]; +- u16 negative_limit; +- u8 enables; +- u8 white; +- u8 black; +- u8 grey; +-}; +- +-struct pisp_be_sh_fc_combine_config { +- u8 y_factor; +- u8 c1_factor; +- u8 c2_factor; +- u8 pad; +-}; +- +-#define PISP_BE_GAMMA_LUT_SIZE 64 +- +-struct pisp_be_gamma_config { +- u32 lut[PISP_BE_GAMMA_LUT_SIZE]; +-}; +- +-struct pisp_be_crop_config { +- u16 offset_x, offset_y; +- u16 width, height; +-}; +- +-#define PISP_BE_RESAMPLE_FILTER_SIZE 96 +- +-struct pisp_be_resample_config { +- u16 scale_factor_h, scale_factor_v; +- s16 coef[PISP_BE_RESAMPLE_FILTER_SIZE]; +-}; +- +-struct pisp_be_resample_extra { +- u16 scaled_width; +- u16 scaled_height; +- s16 initial_phase_h[3]; +- s16 initial_phase_v[3]; +-}; +- +-struct pisp_be_downscale_config { +- u16 scale_factor_h; +- u16 scale_factor_v; +- u16 scale_recip_h; +- u16 scale_recip_v; +-}; +- +-struct pisp_be_downscale_extra { +- u16 scaled_width; +- u16 scaled_height; +-}; +- +-struct pisp_be_hog_config { +- u8 compute_signed; +- u8 channel_mix[3]; +- u32 stride; +-}; +- +-struct pisp_be_axi_config { +- u8 r_qos; /* Read QoS */ +- u8 r_cache_prot; /* Read { prot[2:0], cache[3:0] } */ +- u8 w_qos; /* Write QoS */ +- u8 w_cache_prot; /* Write { prot[2:0], cache[3:0] } */ +-}; +- +-enum pisp_be_transform { +- PISP_BE_TRANSFORM_NONE = 0x0, +- PISP_BE_TRANSFORM_HFLIP = 0x1, +- PISP_BE_TRANSFORM_VFLIP = 0x2, +- PISP_BE_TRANSFORM_ROT180 = +- (PISP_BE_TRANSFORM_HFLIP | PISP_BE_TRANSFORM_VFLIP) +-}; +- +-struct pisp_be_output_format_config { +- struct pisp_image_format_config image; +- u8 transform; +- u8 pad[3]; +- u16 lo; +- u16 hi; +- u16 lo2; +- u16 hi2; +-}; +- +-struct pisp_be_output_buffer_config { +- /* low 32 bits followed by high 32 bits (for each of 3 planes) */ +- u32 addr[3][2]; +-}; +- +-struct pisp_be_hog_buffer_config { +- /* low 32 bits followed by high 32 bits */ +- u32 addr[2]; +-}; +- +-struct pisp_be_config { +- /* I/O configuration: */ +- struct pisp_be_input_buffer_config input_buffer; +- struct pisp_be_tdn_input_buffer_config tdn_input_buffer; +- struct pisp_be_stitch_input_buffer_config stitch_input_buffer; +- struct pisp_be_tdn_output_buffer_config tdn_output_buffer; +- struct pisp_be_stitch_output_buffer_config stitch_output_buffer; +- struct pisp_be_output_buffer_config +- output_buffer[PISP_BACK_END_NUM_OUTPUTS]; +- struct pisp_be_hog_buffer_config hog_buffer; +- /* Processing configuration: */ +- struct pisp_be_global_config global; +- struct pisp_image_format_config input_format; +- struct pisp_decompress_config decompress; +- struct pisp_be_dpc_config dpc; +- struct pisp_be_geq_config geq; +- struct pisp_image_format_config tdn_input_format; +- struct pisp_decompress_config tdn_decompress; +- struct pisp_be_tdn_config tdn; +- struct pisp_compress_config tdn_compress; +- struct pisp_image_format_config tdn_output_format; +- struct pisp_be_sdn_config sdn; +- struct pisp_bla_config blc; +- struct pisp_compress_config stitch_compress; +- struct pisp_image_format_config stitch_output_format; +- struct pisp_image_format_config stitch_input_format; +- struct pisp_decompress_config stitch_decompress; +- struct pisp_be_stitch_config stitch; +- struct pisp_be_lsc_config lsc; +- struct pisp_wbg_config wbg; +- struct pisp_be_cdn_config cdn; +- struct pisp_be_cac_config cac; +- struct pisp_be_debin_config debin; +- struct pisp_be_tonemap_config tonemap; +- struct pisp_be_demosaic_config demosaic; +- struct pisp_be_ccm_config ccm; +- struct pisp_be_sat_control_config sat_control; +- struct pisp_be_ccm_config ycbcr; +- struct pisp_be_sharpen_config sharpen; +- struct pisp_be_false_colour_config false_colour; +- struct pisp_be_sh_fc_combine_config sh_fc_combine; +- struct pisp_be_ccm_config ycbcr_inverse; +- struct pisp_be_gamma_config gamma; +- struct pisp_be_ccm_config csc[PISP_BACK_END_NUM_OUTPUTS]; +- struct pisp_be_downscale_config downscale[PISP_BACK_END_NUM_OUTPUTS]; +- struct pisp_be_resample_config resample[PISP_BACK_END_NUM_OUTPUTS]; +- struct pisp_be_output_format_config +- output_format[PISP_BACK_END_NUM_OUTPUTS]; +- struct pisp_be_hog_config hog; +- struct pisp_be_axi_config axi; +- /* Non-register fields: */ +- struct pisp_be_lsc_extra lsc_extra; +- struct pisp_be_cac_extra cac_extra; +- struct pisp_be_downscale_extra +- downscale_extra[PISP_BACK_END_NUM_OUTPUTS]; +- struct pisp_be_resample_extra resample_extra[PISP_BACK_END_NUM_OUTPUTS]; +- struct pisp_be_crop_config crop; +- struct pisp_image_format_config hog_format; +- u32 dirty_flags_bayer; /* these use pisp_be_bayer_enable */ +- u32 dirty_flags_rgb; /* use pisp_be_rgb_enable */ +- u32 dirty_flags_extra; /* these use pisp_be_dirty_t */ +-}; +- +-/* +- * We also need a tile structure to describe the size of the tiles going +- * through the pipeline. +- */ +- +-enum pisp_tile_edge { +- PISP_LEFT_EDGE = (1 << 0), +- PISP_RIGHT_EDGE = (1 << 1), +- PISP_TOP_EDGE = (1 << 2), +- PISP_BOTTOM_EDGE = (1 << 3) +-}; +- +-struct pisp_tile { +- u8 edge; // enum pisp_tile_edge +- u8 pad0[3]; +- // 4 bytes +- u32 input_addr_offset; +- u32 input_addr_offset2; +- u16 input_offset_x; +- u16 input_offset_y; +- u16 input_width; +- u16 input_height; +- // 20 bytes +- u32 tdn_input_addr_offset; +- u32 tdn_output_addr_offset; +- u32 stitch_input_addr_offset; +- u32 stitch_output_addr_offset; +- // 36 bytes +- u32 lsc_grid_offset_x; +- u32 lsc_grid_offset_y; +- // 44 bytes +- u32 cac_grid_offset_x; +- u32 cac_grid_offset_y; +- // 52 bytes +- u16 crop_x_start[PISP_BACK_END_NUM_OUTPUTS]; +- u16 crop_x_end[PISP_BACK_END_NUM_OUTPUTS]; +- u16 crop_y_start[PISP_BACK_END_NUM_OUTPUTS]; +- u16 crop_y_end[PISP_BACK_END_NUM_OUTPUTS]; +- // 68 bytes +- /* Ordering is planes then branches */ +- u16 downscale_phase_x[3 * PISP_BACK_END_NUM_OUTPUTS]; +- u16 downscale_phase_y[3 * PISP_BACK_END_NUM_OUTPUTS]; +- // 92 bytes +- u16 resample_in_width[PISP_BACK_END_NUM_OUTPUTS]; +- u16 resample_in_height[PISP_BACK_END_NUM_OUTPUTS]; +- // 100 bytes +- /* Ordering is planes then branches */ +- u16 resample_phase_x[3 * PISP_BACK_END_NUM_OUTPUTS]; +- u16 resample_phase_y[3 * PISP_BACK_END_NUM_OUTPUTS]; +- // 124 bytes +- u16 output_offset_x[PISP_BACK_END_NUM_OUTPUTS]; +- u16 output_offset_y[PISP_BACK_END_NUM_OUTPUTS]; +- u16 output_width[PISP_BACK_END_NUM_OUTPUTS]; +- u16 output_height[PISP_BACK_END_NUM_OUTPUTS]; +- // 140 bytes +- u32 output_addr_offset[PISP_BACK_END_NUM_OUTPUTS]; +- u32 output_addr_offset2[PISP_BACK_END_NUM_OUTPUTS]; +- // 156 bytes +- u32 output_hog_addr_offset; +- // 160 bytes +-}; +- +-static_assert(sizeof(struct pisp_tile) == 160); +- +-struct pisp_be_tiles_config { +- struct pisp_be_config config; +- struct pisp_tile tiles[PISP_BACK_END_NUM_TILES]; +- int num_tiles; +-}; +- +-#endif /* _PISP_BE_CONFIG_H_ */ +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be_formats.h +@@ -2,7 +2,7 @@ + /* + * PiSP Back End driver image format definitions. + * +- * Copyright (c) 2021 Raspberry Pi Ltd ++ * Copyright (c) 2021-2024 Raspberry Pi Ltd + */ + + #ifndef _PISP_BE_FORMATS_ +@@ -11,15 +11,15 @@ + #include + #include + +-#define MAX_PLANES 3 +-#define P3(x) ((x) * 8) ++#define PISPBE_MAX_PLANES 3 ++#define P3(x) ((x) * 8) + + struct pisp_be_format { + unsigned int fourcc; + unsigned int align; + unsigned int bit_depth; + /* 0P3 factor for plane sizing */ +- unsigned int plane_factor[MAX_PLANES]; ++ unsigned int plane_factor[PISPBE_MAX_PLANES]; + unsigned int num_planes; + unsigned int colorspace_mask; + enum v4l2_colorspace colorspace_default; +@@ -27,14 +27,19 @@ struct pisp_be_format { + + #define V4L2_COLORSPACE_MASK(colorspace) BIT(colorspace) + +-#define V4L2_COLORSPACE_MASK_JPEG V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_JPEG) +-#define V4L2_COLORSPACE_MASK_SMPTE170M V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_SMPTE170M) +-#define V4L2_COLORSPACE_MASK_REC709 V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_REC709) +-#define V4L2_COLORSPACE_MASK_SRGB V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_SRGB) +-#define V4L2_COLORSPACE_MASK_RAW V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_RAW) ++#define V4L2_COLORSPACE_MASK_JPEG \ ++ V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_JPEG) ++#define V4L2_COLORSPACE_MASK_SMPTE170M \ ++ V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_SMPTE170M) ++#define V4L2_COLORSPACE_MASK_REC709 \ ++ V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_REC709) ++#define V4L2_COLORSPACE_MASK_SRGB \ ++ V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_SRGB) ++#define V4L2_COLORSPACE_MASK_RAW \ ++ V4L2_COLORSPACE_MASK(V4L2_COLORSPACE_RAW) + + /* +- * All three colour spaces JPEG, SMPTE170M and REC709 are fundamentally sRGB ++ * All three colour spaces SRGB, SMPTE170M and REC709 are fundamentally sRGB + * underneath (as near as makes no difference to us), just with different YCbCr + * encodings. Therefore the ISP can generate sRGB on its main output and any of + * the others on its low resolution output. Applications should, when using both +@@ -43,9 +48,9 @@ struct pisp_be_format { + * producing an RGB format. In turn this requires us to allow all these colour + * spaces for every YUV/RGB output format. + */ +-#define V4L2_COLORSPACE_MASK_ALL_SRGB (V4L2_COLORSPACE_MASK_JPEG | \ +- V4L2_COLORSPACE_MASK_SRGB | \ +- V4L2_COLORSPACE_MASK_SMPTE170M | \ ++#define V4L2_COLORSPACE_MASK_ALL_SRGB (V4L2_COLORSPACE_MASK_JPEG | \ ++ V4L2_COLORSPACE_MASK_SRGB | \ ++ V4L2_COLORSPACE_MASK_SMPTE170M | \ + V4L2_COLORSPACE_MASK_REC709) + + static const struct pisp_be_format supported_formats[] = { +@@ -58,7 +63,7 @@ static const struct pisp_be_format suppo + .plane_factor = { P3(1), P3(0.25), P3(0.25) }, + .num_planes = 1, + .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, +- .colorspace_default = V4L2_COLORSPACE_JPEG, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, + }, + { + .fourcc = V4L2_PIX_FMT_YVU420, +@@ -132,7 +137,7 @@ static const struct pisp_be_format suppo + .plane_factor = { P3(1), P3(0.25), P3(0.25) }, + .num_planes = 3, + .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, +- .colorspace_default = V4L2_COLORSPACE_JPEG, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, + }, + { + .fourcc = V4L2_PIX_FMT_NV12M, +@@ -168,7 +173,7 @@ static const struct pisp_be_format suppo + .plane_factor = { P3(1), P3(0.5), P3(0.5) }, + .num_planes = 3, + .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, +- .colorspace_default = V4L2_COLORSPACE_JPEG, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, + }, + { + .fourcc = V4L2_PIX_FMT_YVU422M, +@@ -186,7 +191,7 @@ static const struct pisp_be_format suppo + .plane_factor = { P3(1), P3(1), P3(1) }, + .num_planes = 3, + .colorspace_mask = V4L2_COLORSPACE_MASK_ALL_SRGB, +- .colorspace_default = V4L2_COLORSPACE_JPEG, ++ .colorspace_default = V4L2_COLORSPACE_SMPTE170M, + }, + { + .fourcc = V4L2_PIX_FMT_YVU444M, +@@ -502,11 +507,6 @@ static const struct pisp_be_format suppo + .colorspace_mask = V4L2_COLORSPACE_MASK_RAW, + .colorspace_default = V4L2_COLORSPACE_RAW, + }, +- /* Opaque BE format for HW verification. */ +- { +- .fourcc = V4L2_PIX_FMT_RPI_BE, +- .align = 32, +- }, + }; + + static const struct pisp_be_format meta_out_supported_formats[] = { diff --git a/target/linux/bcm27xx/patches-6.6/950-1155-media-uapi-pisp_be_config-Drop-BIT-from-uAPI.patch b/target/linux/bcm27xx/patches-6.6/950-1155-media-uapi-pisp_be_config-Drop-BIT-from-uAPI.patch new file mode 100644 index 0000000000..f59c02c5b1 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1155-media-uapi-pisp_be_config-Drop-BIT-from-uAPI.patch @@ -0,0 +1,29 @@ +From b58aeea7e2e3afd4fb3b6dcbe5e382b2244b33a4 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Thu, 27 Jun 2024 13:40:29 +0200 +Subject: [PATCH 1155/1215] media: uapi: pisp_be_config: Drop BIT() from uAPI + +The pisp_be_config.h uAPI header file contains a bit-field definition +that uses the BIT() helper macro. + +As the BIT() identifier is not defined in userspace, drop it from the +uAPI header. + +Fixes: c6c49bac8770 ("media: uapi: Add Raspberry Pi PiSP Back End uAPI") +Signed-off-by: Jacopo Mondi +Reviewed-by: Tomi Valkeinen +--- + include/uapi/linux/media/raspberrypi/pisp_be_config.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/uapi/linux/media/raspberrypi/pisp_be_config.h ++++ b/include/uapi/linux/media/raspberrypi/pisp_be_config.h +@@ -146,7 +146,7 @@ struct pisp_be_dpc_config { + */ + struct pisp_be_geq_config { + __u16 offset; +-#define PISP_BE_GEQ_SHARPER BIT(15) ++#define PISP_BE_GEQ_SHARPER (1U << 15) + #define PISP_BE_GEQ_SLOPE ((1 << 10) - 1) + /* top bit is the "sharper" flag, slope value is bottom 10 bits */ + __u16 slope_sharper; diff --git a/target/linux/bcm27xx/patches-6.6/950-1156-media-uapi-pisp_common-Add-32-bpp-format-test.patch b/target/linux/bcm27xx/patches-6.6/950-1156-media-uapi-pisp_common-Add-32-bpp-format-test.patch new file mode 100644 index 0000000000..0cb94fe933 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1156-media-uapi-pisp_common-Add-32-bpp-format-test.patch @@ -0,0 +1,32 @@ +From 7c36a1feb61d964055bee777efc1db60790aa215 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Thu, 27 Jun 2024 16:07:43 +0200 +Subject: [PATCH 1156/1215] media: uapi: pisp_common: Add 32 bpp format test + +Add definition and test for 32-bits image formats to the pisp_common.h +uAPI header. + +Signed-off-by: Jacopo Mondi +--- + include/uapi/linux/media/raspberrypi/pisp_common.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/uapi/linux/media/raspberrypi/pisp_common.h ++++ b/include/uapi/linux/media/raspberrypi/pisp_common.h +@@ -72,6 +72,8 @@ enum pisp_image_format { + PISP_IMAGE_FORMAT_SHIFT_8 = 0x00080000, + PISP_IMAGE_FORMAT_SHIFT_MASK = 0x000f0000, + ++ PISP_IMAGE_FORMAT_BPP_32 = 0x00100000, ++ + PISP_IMAGE_FORMAT_UNCOMPRESSED = 0x00000000, + PISP_IMAGE_FORMAT_COMPRESSION_MODE_1 = 0x01000000, + PISP_IMAGE_FORMAT_COMPRESSION_MODE_2 = 0x02000000, +@@ -134,6 +136,7 @@ enum pisp_image_format { + PISP_IMAGE_FORMAT_PLANARITY_PLANAR) + #define PISP_IMAGE_FORMAT_wallpaper(fmt) \ + ((fmt) & PISP_IMAGE_FORMAT_WALLPAPER_ROLL) ++#define PISP_IMAGE_FORMAT_bpp_32(fmt) ((fmt) & PISP_IMAGE_FORMAT_BPP_32) + #define PISP_IMAGE_FORMAT_HOG(fmt) \ + ((fmt) & \ + (PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED)) diff --git a/target/linux/bcm27xx/patches-6.6/950-1157-media-uapi-Capitalize-all-macros.patch b/target/linux/bcm27xx/patches-6.6/950-1157-media-uapi-Capitalize-all-macros.patch new file mode 100644 index 0000000000..fac2ccf163 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1157-media-uapi-Capitalize-all-macros.patch @@ -0,0 +1,89 @@ +From 20a3671be178fd98aac08931d809e689eaa7a9d9 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 28 Jun 2024 10:10:10 +0200 +Subject: [PATCH 1157/1215] media: uapi: Capitalize all macros + +The macro used to inspect an image format characteristic use a mixture +of capitalized and non-capitalized letters, which is rather unusual for +the Linux kernel style. + +Capitalize all identifiers. + +Signed-off-by: Jacopo Mondi +--- + .../linux/media/raspberrypi/pisp_common.h | 38 +++++++++---------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +--- a/include/uapi/linux/media/raspberrypi/pisp_common.h ++++ b/include/uapi/linux/media/raspberrypi/pisp_common.h +@@ -92,51 +92,51 @@ enum pisp_image_format { + PISP_IMAGE_FORMAT_THREE_CHANNEL + }; + +-#define PISP_IMAGE_FORMAT_bps_8(fmt) \ ++#define PISP_IMAGE_FORMAT_BPS_8(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_8) +-#define PISP_IMAGE_FORMAT_bps_10(fmt) \ ++#define PISP_IMAGE_FORMAT_BPS_10(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_10) +-#define PISP_IMAGE_FORMAT_bps_12(fmt) \ ++#define PISP_IMAGE_FORMAT_BPS_12(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_12) +-#define PISP_IMAGE_FORMAT_bps_16(fmt) \ ++#define PISP_IMAGE_FORMAT_BPS_16(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) == PISP_IMAGE_FORMAT_BPS_16) +-#define PISP_IMAGE_FORMAT_bps(fmt) \ ++#define PISP_IMAGE_FORMAT_BPS(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) ? \ + 8 + (2 << (((fmt) & PISP_IMAGE_FORMAT_BPS_MASK) - 1)) : 8) +-#define PISP_IMAGE_FORMAT_shift(fmt) \ ++#define PISP_IMAGE_FORMAT_SHIFT(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_SHIFT_MASK) / PISP_IMAGE_FORMAT_SHIFT_1) +-#define PISP_IMAGE_FORMAT_three_channel(fmt) \ ++#define PISP_IMAGE_FORMAT_THREE_CHANNEL(fmt) \ + ((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL) +-#define PISP_IMAGE_FORMAT_single_channel(fmt) \ ++#define PISP_IMAGE_FORMAT_SINGLE_CHANNEL(fmt) \ + (!((fmt) & PISP_IMAGE_FORMAT_THREE_CHANNEL)) +-#define PISP_IMAGE_FORMAT_compressed(fmt) \ ++#define PISP_IMAGE_FORMAT_COMPRESSED(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_COMPRESSION_MASK) != \ + PISP_IMAGE_FORMAT_UNCOMPRESSED) +-#define PISP_IMAGE_FORMAT_sampling_444(fmt) \ ++#define PISP_IMAGE_FORMAT_SAMPLING_444(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ + PISP_IMAGE_FORMAT_SAMPLING_444) +-#define PISP_IMAGE_FORMAT_sampling_422(fmt) \ ++#define PISP_IMAGE_FORMAT_SAMPLING_422(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ + PISP_IMAGE_FORMAT_SAMPLING_422) +-#define PISP_IMAGE_FORMAT_sampling_420(fmt) \ ++#define PISP_IMAGE_FORMAT_SAMPLING_420(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_SAMPLING_MASK) == \ + PISP_IMAGE_FORMAT_SAMPLING_420) +-#define PISP_IMAGE_FORMAT_order_normal(fmt) \ ++#define PISP_IMAGE_FORMAT_ORDER_NORMAL(fmt) \ + (!((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED)) +-#define PISP_IMAGE_FORMAT_order_swapped(fmt) \ ++#define PISP_IMAGE_FORMAT_ORDER_SWAPPED(fmt) \ + ((fmt) & PISP_IMAGE_FORMAT_ORDER_SWAPPED) +-#define PISP_IMAGE_FORMAT_interleaved(fmt) \ ++#define PISP_IMAGE_FORMAT_INTERLEAVED(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ + PISP_IMAGE_FORMAT_PLANARITY_INTERLEAVED) +-#define PISP_IMAGE_FORMAT_semiplanar(fmt) \ ++#define PISP_IMAGE_FORMAT_SEMIPLANAR(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ + PISP_IMAGE_FORMAT_PLANARITY_SEMI_PLANAR) +-#define PISP_IMAGE_FORMAT_planar(fmt) \ ++#define PISP_IMAGE_FORMAT_PLANAR(fmt) \ + (((fmt) & PISP_IMAGE_FORMAT_PLANARITY_MASK) == \ + PISP_IMAGE_FORMAT_PLANARITY_PLANAR) +-#define PISP_IMAGE_FORMAT_wallpaper(fmt) \ ++#define PISP_IMAGE_FORMAT_WALLPAPER(fmt) \ + ((fmt) & PISP_IMAGE_FORMAT_WALLPAPER_ROLL) +-#define PISP_IMAGE_FORMAT_bpp_32(fmt) ((fmt) & PISP_IMAGE_FORMAT_BPP_32) ++#define PISP_IMAGE_FORMAT_BPP_32(fmt) ((fmt) & PISP_IMAGE_FORMAT_BPP_32) + #define PISP_IMAGE_FORMAT_HOG(fmt) \ + ((fmt) & \ + (PISP_IMAGE_FORMAT_HOG_SIGNED | PISP_IMAGE_FORMAT_HOG_UNSIGNED)) diff --git a/target/linux/bcm27xx/patches-6.6/950-1158-media-uapi-pisp_be_config-Re-sort-pisp_be_tiles_conf.patch b/target/linux/bcm27xx/patches-6.6/950-1158-media-uapi-pisp_be_config-Re-sort-pisp_be_tiles_conf.patch new file mode 100644 index 0000000000..49ff9d73ff --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1158-media-uapi-pisp_be_config-Re-sort-pisp_be_tiles_conf.patch @@ -0,0 +1,30 @@ +From ce89955e44f3ab41262b02d8e1e65c3455d66c4d Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 28 Jun 2024 13:59:40 +0200 +Subject: [PATCH 1158/1215] media: uapi: pisp_be_config: Re-sort + pisp_be_tiles_config + +The order of the members of pisp_be_tiles_config is relevant +as the driver logic assumes 'config' to be at offset 0. + +Re-sort the member to match the driver's expectations. + +Fixes: c6c49bac8770 ("media: uapi: Add Raspberry Pi PiSP Back End uAPI") +Signed-off-by: Jacopo Mondi +--- + include/uapi/linux/media/raspberrypi/pisp_be_config.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/uapi/linux/media/raspberrypi/pisp_be_config.h ++++ b/include/uapi/linux/media/raspberrypi/pisp_be_config.h +@@ -919,9 +919,9 @@ struct pisp_tile { + * @config: PiSP Back End configuration + */ + struct pisp_be_tiles_config { ++ struct pisp_be_config config; + struct pisp_tile tiles[PISP_BACK_END_NUM_TILES]; + __u32 num_tiles; +- struct pisp_be_config config; + } __attribute__((packed)); + + #endif /* _UAPI_PISP_BE_CONFIG_H_ */ diff --git a/target/linux/bcm27xx/patches-6.6/950-1159-media-uapi-pisp_be_config-Add-extra-config-fields.patch b/target/linux/bcm27xx/patches-6.6/950-1159-media-uapi-pisp_be_config-Add-extra-config-fields.patch new file mode 100644 index 0000000000..d18d12ec67 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1159-media-uapi-pisp_be_config-Add-extra-config-fields.patch @@ -0,0 +1,82 @@ +From abf30420f943d03cc28fec38612d2c5f5e6edf1f Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 28 Jun 2024 14:11:14 +0200 +Subject: [PATCH 1159/1215] media: uapi: pisp_be_config: Add extra config + fields + +Complete the pisp_be_config strcture by adding fields that even if not +written to the HW are relevant to complete the uAPI and put it in par +with the BSP driver. + +Fixes: c6c49bac8770 ("media: uapi: Add Raspberry Pi PiSP Back End uAPI") +Signed-off-by: Jacopo Mondi +--- + .../linux/media/raspberrypi/pisp_be_config.h | 41 +++++++++++++++++++ + 1 file changed, 41 insertions(+) + +--- a/include/uapi/linux/media/raspberrypi/pisp_be_config.h ++++ b/include/uapi/linux/media/raspberrypi/pisp_be_config.h +@@ -716,6 +716,13 @@ struct pisp_be_hog_buffer_config { + /** + * struct pisp_be_config - RaspberryPi PiSP Back End Processing configuration + * ++ * @input_buffer: Input buffer addresses ++ * @tdn_input_buffer: TDN input buffer addresses ++ * @stitch_input_buffer: Stitch input buffer addresses ++ * @tdn_output_buffer: TDN output buffer addresses ++ * @stitch_output_buffer: Stitch output buffer addresses ++ * @output_buffer: Output buffers addresses ++ * @hog_buffer: HOG buffer addresses + * @global: Global PiSP configuration + * @input_format: Input image format + * @decompress: Decompress configuration +@@ -753,8 +760,30 @@ struct pisp_be_hog_buffer_config { + * @resample: Resampling configuration + * @output_format: Output format configuration + * @hog: HOG configuration ++ * @axi: AXI bus configuration ++ * @lsc_extra: LSC extra info ++ * @cac_extra: CAC extra info ++ * @downscale_extra: Downscaler extra info ++ * @resample_extra: Resample extra info ++ * @crop: Crop configuration ++ * @hog_format: HOG format info ++ * @dirty_flags_bayer: Bayer enable dirty flags ++ * (:c:type:`pisp_be_bayer_enable`) ++ * @dirty_flags_rgb: RGB enable dirty flags ++ * (:c:type:`pisp_be_rgb_enable`) ++ * @dirty_flags_extra: Extra dirty flags + */ + struct pisp_be_config { ++ /* I/O configuration: */ ++ struct pisp_be_input_buffer_config input_buffer; ++ struct pisp_be_tdn_input_buffer_config tdn_input_buffer; ++ struct pisp_be_stitch_input_buffer_config stitch_input_buffer; ++ struct pisp_be_tdn_output_buffer_config tdn_output_buffer; ++ struct pisp_be_stitch_output_buffer_config stitch_output_buffer; ++ struct pisp_be_output_buffer_config ++ output_buffer[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_hog_buffer_config hog_buffer; ++ /* Processing configuration: */ + struct pisp_be_global_config global; + struct pisp_image_format_config input_format; + struct pisp_decompress_config decompress; +@@ -793,6 +822,18 @@ struct pisp_be_config { + struct pisp_be_output_format_config + output_format[PISP_BACK_END_NUM_OUTPUTS]; + struct pisp_be_hog_config hog; ++ struct pisp_be_axi_config axi; ++ /* Non-register fields: */ ++ struct pisp_be_lsc_extra lsc_extra; ++ struct pisp_be_cac_extra cac_extra; ++ struct pisp_be_downscale_extra ++ downscale_extra[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_resample_extra resample_extra[PISP_BACK_END_NUM_OUTPUTS]; ++ struct pisp_be_crop_config crop; ++ struct pisp_image_format_config hog_format; ++ __u32 dirty_flags_bayer; /* these use pisp_be_bayer_enable */ ++ __u32 dirty_flags_rgb; /* use pisp_be_rgb_enable */ ++ __u32 dirty_flags_extra; /* these use pisp_be_dirty_t */ + } __attribute__((packed)); + + /** diff --git a/target/linux/bcm27xx/patches-6.6/950-1160-media-pisp_be-Re-introduce-multi-context-support.patch b/target/linux/bcm27xx/patches-6.6/950-1160-media-pisp_be-Re-introduce-multi-context-support.patch new file mode 100644 index 0000000000..ad667a1e69 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1160-media-pisp_be-Re-introduce-multi-context-support.patch @@ -0,0 +1,886 @@ +From 033e037013f2c092501a03bb1bf5bbf7b4045aa0 Mon Sep 17 00:00:00 2001 +From: Jacopo Mondi +Date: Fri, 28 Jun 2024 17:26:26 +0200 +Subject: [PATCH 1160/1215] media: pisp_be: Re-introduce multi-context support + +Re-introduce multi-context support that was dropped from the +mainline driver version. + +Signed-off-by: Jacopo Mondi +--- + .../platform/raspberrypi/pisp_be/pisp_be.c | 355 ++++++++++-------- + 1 file changed, 208 insertions(+), 147 deletions(-) + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +@@ -24,6 +24,14 @@ + /* Maximum number of config buffers possible */ + #define PISP_BE_NUM_CONFIG_BUFFERS VB2_MAX_FRAME + ++/* ++ * We want to support 2 independent instances allowing 2 simultaneous users ++ * of the ISP-BE (of course they share hardware, platform resources and mutex). ++ * Each such instance comprises a group of device nodes representing input ++ * and output queues, and a media controller device node to describe them. ++ */ ++#define PISPBE_NUM_NODE_GROUPS 2 ++ + #define PISPBE_NAME "pispbe" + + /* Some ISP-BE registers */ +@@ -156,7 +164,7 @@ struct pispbe_node { + struct media_pad pad; + struct media_intf_devnode *intf_devnode; + struct media_link *intf_link; +- struct pispbe_dev *pispbe; ++ struct pispbe_node_group *node_group; + /* Video device lock */ + struct mutex node_lock; + /* vb2_queue lock */ +@@ -173,9 +181,27 @@ struct pispbe_node { + #define NODE_NAME(node) \ + (node_desc[(node)->id].ent_name + sizeof(PISPBE_NAME)) + ++/* ++ * Node group structure, which comprises all the input and output nodes that a ++ * single PiSP client will need, along with its own v4l2 and media devices. ++ */ ++struct pispbe_node_group { ++ unsigned int id; ++ struct v4l2_device v4l2_dev; ++ struct v4l2_subdev sd; ++ struct pispbe_dev *pispbe; ++ struct media_device mdev; ++ struct pispbe_node node[PISPBE_NUM_NODES]; ++ u32 streaming_map; /* bitmap of which nodes are streaming */ ++ struct media_pad pad[PISPBE_NUM_NODES]; /* output pads first */ ++ struct pisp_be_tiles_config *config; ++ dma_addr_t config_dma_addr; ++ unsigned int sequence; ++}; ++ + /* Records details of the jobs currently running or queued on the h/w. */ + struct pispbe_job { +- bool valid; ++ struct pispbe_node_group *node_group; + /* + * An array of buffer pointers - remember it's source buffers first, + * then captures, then metadata last. +@@ -198,22 +224,13 @@ struct pispbe_job_descriptor { + + /* + * Structure representing the entire PiSP Back End device, comprising several +- * nodes which share platform resources and a mutex for the actual HW. ++ * nodes groups which share platform resources and a mutex for the actual HW. + */ + struct pispbe_dev { + struct device *dev; +- struct pispbe_dev *pispbe; +- struct pisp_be_tiles_config *config; + void __iomem *be_reg_base; + struct clk *clk; +- struct v4l2_device v4l2_dev; +- struct v4l2_subdev sd; +- struct media_device mdev; +- struct media_pad pad[PISPBE_NUM_NODES]; /* output pads first */ +- struct pispbe_node node[PISPBE_NUM_NODES]; +- dma_addr_t config_dma_addr; +- unsigned int sequence; +- u32 streaming_map; ++ struct pispbe_node_group node_group[PISPBE_NUM_NODE_GROUPS]; + struct pispbe_job queued_job, running_job; + spinlock_t hw_lock; /* protects "hw_busy" flag and streaming_map */ + bool hw_busy; /* non-zero if a job is queued or is being started */ +@@ -348,9 +365,9 @@ static dma_addr_t pispbe_get_addr(struct + return 0; + } + +-static void pispbe_xlate_addrs(struct pispbe_dev *pispbe, +- struct pispbe_job_descriptor *job, +- struct pispbe_buffer *buf[PISPBE_NUM_NODES]) ++static void pispbe_xlate_addrs(struct pispbe_job_descriptor *job, ++ struct pispbe_buffer *buf[PISPBE_NUM_NODES], ++ struct pispbe_node_group *node_group) + { + struct pispbe_hw_enables *hw_en = &job->hw_enables; + struct pisp_be_tiles_config *config = job->config; +@@ -366,13 +383,13 @@ static void pispbe_xlate_addrs(struct pi + * to 3 planes. + */ + ret = pispbe_get_planes_addr(addrs, buf[MAIN_INPUT_NODE], +- &pispbe->node[MAIN_INPUT_NODE]); ++ &node_group->node[MAIN_INPUT_NODE]); + if (ret <= 0) { + /* + * This shouldn't happen; pispbe_schedule_internal should insist + * on an input. + */ +- dev_warn(pispbe->dev, "ISP-BE missing input\n"); ++ dev_warn(node_group->pispbe->dev, "ISP-BE missing input\n"); + hw_en->bayer_enables = 0; + hw_en->rgb_enables = 0; + return; +@@ -427,7 +444,7 @@ static void pispbe_xlate_addrs(struct pi + for (unsigned int i = 0; i < PISP_BACK_END_NUM_OUTPUTS; i++) { + ret = pispbe_get_planes_addr(addrs + 7 + 3 * i, + buf[OUTPUT0_NODE + i], +- &pispbe->node[OUTPUT0_NODE + i]); ++ &node_group->node[OUTPUT0_NODE + i]); + if (ret <= 0) + hw_en->rgb_enables &= ~(PISP_BE_RGB_ENABLE_OUTPUT0 << i); + } +@@ -447,10 +464,11 @@ static void pispbe_xlate_addrs(struct pi + * + * Returns 0 if a job has been successfully prepared, < 0 otherwise. + */ +-static int pispbe_prepare_job(struct pispbe_dev *pispbe, ++static int pispbe_prepare_job(struct pispbe_node_group *node_group, + struct pispbe_job_descriptor *job) + { + struct pispbe_buffer *buf[PISPBE_NUM_NODES] = {}; ++ struct pispbe_dev *pispbe = node_group->pispbe; + unsigned int config_index; + struct pispbe_node *node; + unsigned long flags; +@@ -460,11 +478,11 @@ static int pispbe_prepare_job(struct pis + memset(job, 0, sizeof(struct pispbe_job_descriptor)); + + if (((BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE)) & +- pispbe->streaming_map) != ++ node_group->streaming_map) != + (BIT(CONFIG_NODE) | BIT(MAIN_INPUT_NODE))) + return -ENODEV; + +- node = &pispbe->node[CONFIG_NODE]; ++ node = &node_group->node[CONFIG_NODE]; + spin_lock_irqsave(&node->ready_lock, flags); + buf[CONFIG_NODE] = list_first_entry_or_null(&node->ready_queue, + struct pispbe_buffer, +@@ -480,8 +498,8 @@ static int pispbe_prepare_job(struct pis + return -ENODEV; + + config_index = buf[CONFIG_NODE]->vb.vb2_buf.index; +- job->config = &pispbe->config[config_index]; +- job->tiles = pispbe->config_dma_addr + ++ job->config = &node_group->config[config_index]; ++ job->tiles = node_group->config_dma_addr + + config_index * sizeof(struct pisp_be_tiles_config) + + offsetof(struct pisp_be_tiles_config, tiles); + +@@ -498,7 +516,7 @@ static int pispbe_prepare_job(struct pis + continue; + + buf[i] = NULL; +- if (!(pispbe->streaming_map & BIT(i))) ++ if (!(node_group->streaming_map & BIT(i))) + continue; + + if ((!(rgb_en & PISP_BE_RGB_ENABLE_OUTPUT0) && +@@ -522,7 +540,7 @@ static int pispbe_prepare_job(struct pis + ignore_buffers = true; + } + +- node = &pispbe->node[i]; ++ node = &node_group->node[i]; + + /* Pull a buffer from each V4L2 queue to form the queued job */ + spin_lock_irqsave(&node->ready_lock, flags); +@@ -539,16 +557,16 @@ static int pispbe_prepare_job(struct pis + goto err_return_buffers; + } + +- pispbe->queued_job.valid = true; ++ pispbe->queued_job.node_group = node_group; + + /* Convert buffers to DMA addresses for the hardware */ +- pispbe_xlate_addrs(pispbe, job, buf); ++ pispbe_xlate_addrs(job, buf, node_group); + + return 0; + + err_return_buffers: + for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) { +- struct pispbe_node *n = &pispbe->node[i]; ++ struct pispbe_node *n = &node_group->node[i]; + + if (!buf[i]) + continue; +@@ -564,11 +582,12 @@ err_return_buffers: + return -ENODEV; + } + +-static void pispbe_schedule(struct pispbe_dev *pispbe, bool clear_hw_busy) ++static void pispbe_schedule(struct pispbe_dev *pispbe, ++ struct pispbe_node_group *node_group, ++ bool clear_hw_busy) + { + struct pispbe_job_descriptor job; + unsigned long flags; +- int ret; + + spin_lock_irqsave(&pispbe->hw_lock, flags); + +@@ -578,40 +597,53 @@ static void pispbe_schedule(struct pispb + if (pispbe->hw_busy) + goto unlock_and_return; + +- ret = pispbe_prepare_job(pispbe, &job); +- if (ret) +- goto unlock_and_return; ++ for (unsigned int i = 0; i < PISPBE_NUM_NODE_GROUPS; i++) { ++ int ret; + +- /* +- * We can kick the job off without the hw_lock, as this can +- * never run again until hw_busy is cleared, which will happen +- * only when the following job has been queued and an interrupt +- * is rised. +- */ +- pispbe->hw_busy = true; +- spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ /* Schedule jobs only for a specific group. */ ++ if (node_group && &pispbe->node_group[i] != node_group) ++ continue; + +- if (job.config->num_tiles <= 0 || +- job.config->num_tiles > PISP_BACK_END_NUM_TILES || +- !((job.hw_enables.bayer_enables | job.hw_enables.rgb_enables) & +- PISP_BE_BAYER_ENABLE_INPUT)) { + /* +- * Bad job. We can't let it proceed as it could lock up +- * the hardware, or worse! +- * +- * For now, just force num_tiles to 0, which causes the +- * H/W to do something bizarre but survivable. It +- * increments (started,done) counters by more than 1, +- * but we seem to survive... ++ * Prepare a job for this group, if the group is not ready ++ * continue and try with the next one. + */ +- dev_dbg(pispbe->dev, "Bad job: invalid number of tiles: %u\n", +- job.config->num_tiles); +- job.config->num_tiles = 0; +- } ++ ret = pispbe_prepare_job(&pispbe->node_group[i], &job); ++ if (ret) ++ continue; ++ ++ /* ++ * We can kick the job off without the hw_lock, as this can ++ * never run again until hw_busy is cleared, which will happen ++ * only when the following job has been queued and an interrupt ++ * is rised. ++ */ ++ pispbe->hw_busy = true; ++ spin_unlock_irqrestore(&pispbe->hw_lock, flags); ++ ++ if (job.config->num_tiles <= 0 || ++ job.config->num_tiles > PISP_BACK_END_NUM_TILES || ++ !((job.hw_enables.bayer_enables | ++ job.hw_enables.rgb_enables) & ++ PISP_BE_BAYER_ENABLE_INPUT)) { ++ /* ++ * Bad job. We can't let it proceed as it could lock up ++ * the hardware, or worse! ++ * ++ * For now, just force num_tiles to 0, which causes the ++ * H/W to do something bizarre but survivable. It ++ * increments (started,done) counters by more than 1, ++ * but we seem to survive... ++ */ ++ dev_dbg(pispbe->dev, "Bad job: invalid number of tiles: %u\n", ++ job.config->num_tiles); ++ job.config->num_tiles = 0; ++ } + +- pispbe_queue_job(pispbe, &job); ++ pispbe_queue_job(pispbe, &job); + +- return; ++ return; ++ } + + unlock_and_return: + /* No job has been queued, just release the lock and return. */ +@@ -627,13 +659,13 @@ static void pispbe_isr_jobdone(struct pi + for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) { + if (buf[i]) { + buf[i]->vb.vb2_buf.timestamp = ts; +- buf[i]->vb.sequence = pispbe->sequence; ++ buf[i]->vb.sequence = job->node_group->sequence; + vb2_buffer_done(&buf[i]->vb.vb2_buf, + VB2_BUF_STATE_DONE); + } + } + +- pispbe->sequence++; ++ job->node_group->sequence++; + } + + static irqreturn_t pispbe_isr(int irq, void *dev) +@@ -657,7 +689,7 @@ static irqreturn_t pispbe_isr(int irq, v + * we previously saw "start" now finishes, and we then queued a new job + * which we see both start and finish "simultaneously". + */ +- if (pispbe->running_job.valid && pispbe->done != done) { ++ if (pispbe->running_job.node_group && pispbe->done != done) { + pispbe_isr_jobdone(pispbe, &pispbe->running_job); + memset(&pispbe->running_job, 0, sizeof(pispbe->running_job)); + pispbe->done++; +@@ -667,7 +699,7 @@ static irqreturn_t pispbe_isr(int irq, v + pispbe->started++; + can_queue_another = 1; + +- if (pispbe->done != done && pispbe->queued_job.valid) { ++ if (pispbe->done != done && pispbe->queued_job.node_group) { + pispbe_isr_jobdone(pispbe, &pispbe->queued_job); + pispbe->done++; + } else { +@@ -686,17 +718,17 @@ static irqreturn_t pispbe_isr(int irq, v + } + + /* check if there's more to do before going to sleep */ +- pispbe_schedule(pispbe, can_queue_another); ++ pispbe_schedule(pispbe, NULL, can_queue_another); + + return IRQ_HANDLED; + } + +-static int pisp_be_validate_config(struct pispbe_dev *pispbe, ++static int pisp_be_validate_config(struct pispbe_node_group *node_group, + struct pisp_be_tiles_config *config) + { + u32 bayer_enables = config->config.global.bayer_enables; + u32 rgb_enables = config->config.global.rgb_enables; +- struct device *dev = pispbe->dev; ++ struct device *dev = node_group->pispbe->dev; + struct v4l2_format *fmt; + unsigned int bpl, size; + +@@ -707,7 +739,7 @@ static int pisp_be_validate_config(struc + } + + /* Ensure output config strides and buffer sizes match the V4L2 formats. */ +- fmt = &pispbe->node[TDN_OUTPUT_NODE].format; ++ fmt = &node_group->node[TDN_OUTPUT_NODE].format; + if (bayer_enables & PISP_BE_BAYER_ENABLE_TDN_OUTPUT) { + bpl = config->config.tdn_output_format.stride; + size = bpl * config->config.tdn_output_format.height; +@@ -725,7 +757,7 @@ static int pisp_be_validate_config(struc + } + } + +- fmt = &pispbe->node[STITCH_OUTPUT_NODE].format; ++ fmt = &node_group->node[STITCH_OUTPUT_NODE].format; + if (bayer_enables & PISP_BE_BAYER_ENABLE_STITCH_OUTPUT) { + bpl = config->config.stitch_output_format.stride; + size = bpl * config->config.stitch_output_format.height; +@@ -751,7 +783,7 @@ static int pisp_be_validate_config(struc + PISP_IMAGE_FORMAT_WALLPAPER_ROLL) + continue; /* TODO: Size checks for wallpaper formats */ + +- fmt = &pispbe->node[OUTPUT0_NODE + j].format; ++ fmt = &node_group->node[OUTPUT0_NODE + j].format; + for (unsigned int i = 0; i < fmt->fmt.pix_mp.num_planes; i++) { + bpl = !i ? config->config.output_format[j].image.stride + : config->config.output_format[j].image.stride2; +@@ -783,7 +815,7 @@ static int pispbe_node_queue_setup(struc + struct device *alloc_devs[]) + { + struct pispbe_node *node = vb2_get_drv_priv(q); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + unsigned int num_planes = NODE_IS_MPLANE(node) ? + node->format.fmt.pix_mp.num_planes : 1; + +@@ -821,7 +853,7 @@ static int pispbe_node_queue_setup(struc + static int pispbe_node_buffer_prepare(struct vb2_buffer *vb) + { + struct pispbe_node *node = vb2_get_drv_priv(vb->vb2_queue); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + unsigned int num_planes = NODE_IS_MPLANE(node) ? + node->format.fmt.pix_mp.num_planes : 1; + +@@ -841,12 +873,12 @@ static int pispbe_node_buffer_prepare(st + } + + if (node->id == CONFIG_NODE) { +- void *dst = &node->pispbe->config[vb->index]; ++ void *dst = &node->node_group->config[vb->index]; + void *src = vb2_plane_vaddr(vb, 0); + + memcpy(dst, src, sizeof(struct pisp_be_tiles_config)); + +- return pisp_be_validate_config(pispbe, dst); ++ return pisp_be_validate_config(node->node_group, dst); + } + + return 0; +@@ -859,7 +891,8 @@ static void pispbe_node_buffer_queue(str + struct pispbe_buffer *buffer = + container_of(vbuf, struct pispbe_buffer, vb); + struct pispbe_node *node = vb2_get_drv_priv(buf->vb2_queue); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_node_group *node_group = node->node_group; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + unsigned long flags; + + dev_dbg(pispbe->dev, "%s: for node %s\n", __func__, NODE_NAME(node)); +@@ -869,15 +902,16 @@ static void pispbe_node_buffer_queue(str + + /* + * Every time we add a buffer, check if there's now some work for the hw +- * to do. ++ * to do, but only for this client. + */ +- pispbe_schedule(pispbe, false); ++ pispbe_schedule(node_group->pispbe, node_group, false); + } + + static int pispbe_node_start_streaming(struct vb2_queue *q, unsigned int count) + { + struct pispbe_node *node = vb2_get_drv_priv(q); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_node_group *node_group = node->node_group; ++ struct pispbe_dev *pispbe = node_group->pispbe; + struct pispbe_buffer *buf, *tmp; + unsigned long flags; + int ret; +@@ -887,17 +921,17 @@ static int pispbe_node_start_streaming(s + goto err_return_buffers; + + spin_lock_irqsave(&pispbe->hw_lock, flags); +- node->pispbe->streaming_map |= BIT(node->id); +- node->pispbe->sequence = 0; ++ node->node_group->streaming_map |= BIT(node->id); ++ node->node_group->sequence = 0; + spin_unlock_irqrestore(&pispbe->hw_lock, flags); + + dev_dbg(pispbe->dev, "%s: for node %s (count %u)\n", + __func__, NODE_NAME(node), count); +- dev_dbg(pispbe->dev, "Nodes streaming now 0x%x\n", +- node->pispbe->streaming_map); ++ dev_dbg(pispbe->dev, "Nodes streaming for this group now 0x%x\n", ++ node->node_group->streaming_map); + + /* Maybe we're ready to run. */ +- pispbe_schedule(pispbe, false); ++ pispbe_schedule(node_group->pispbe, node_group, false); + + return 0; + +@@ -915,7 +949,8 @@ err_return_buffers: + static void pispbe_node_stop_streaming(struct vb2_queue *q) + { + struct pispbe_node *node = vb2_get_drv_priv(q); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_node_group *node_group = node->node_group; ++ struct pispbe_dev *pispbe = node_group->pispbe; + struct pispbe_buffer *buf; + unsigned long flags; + +@@ -948,14 +983,14 @@ static void pispbe_node_stop_streaming(s + vb2_wait_for_all_buffers(&node->queue); + + spin_lock_irqsave(&pispbe->hw_lock, flags); +- pispbe->streaming_map &= ~BIT(node->id); ++ node_group->streaming_map &= ~BIT(node->id); + spin_unlock_irqrestore(&pispbe->hw_lock, flags); + + pm_runtime_mark_last_busy(pispbe->dev); + pm_runtime_put_autosuspend(pispbe->dev); + +- dev_dbg(pispbe->dev, "Nodes streaming now 0x%x\n", +- pispbe->streaming_map); ++ dev_dbg(pispbe->dev, "Nodes streaming for this group now 0x%x\n", ++ node_group->streaming_map); + } + + static const struct vb2_ops pispbe_node_queue_ops = { +@@ -979,7 +1014,7 @@ static int pispbe_node_querycap(struct f + struct v4l2_capability *cap) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + + strscpy(cap->driver, PISPBE_NAME, sizeof(cap->driver)); + strscpy(cap->card, PISPBE_NAME, sizeof(cap->card)); +@@ -995,7 +1030,7 @@ static int pispbe_node_g_fmt_vid_cap(str + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + + if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { + dev_dbg(pispbe->dev, +@@ -1015,7 +1050,7 @@ static int pispbe_node_g_fmt_vid_out(str + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + + if (NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { + dev_dbg(pispbe->dev, +@@ -1035,7 +1070,7 @@ static int pispbe_node_g_fmt_meta_out(st + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + + if (!NODE_IS_META(node) || NODE_IS_CAPTURE(node)) { + dev_dbg(pispbe->dev, +@@ -1092,7 +1127,7 @@ static void pispbe_set_plane_params(stru + + static void pispbe_try_format(struct v4l2_format *f, struct pispbe_node *node) + { +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + u32 pixfmt = f->fmt.pix_mp.pixelformat; + const struct pisp_be_format *fmt; + bool is_rgb; +@@ -1156,7 +1191,7 @@ static int pispbe_node_try_fmt_vid_cap(s + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + + if (!NODE_IS_CAPTURE(node) || NODE_IS_META(node)) { + dev_dbg(pispbe->dev, +@@ -1174,7 +1209,7 @@ static int pispbe_node_try_fmt_vid_out(s + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + + if (!NODE_IS_OUTPUT(node) || NODE_IS_META(node)) { + dev_dbg(pispbe->dev, +@@ -1192,7 +1227,7 @@ static int pispbe_node_try_fmt_meta_out( + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + + if (!NODE_IS_META(node) || NODE_IS_CAPTURE(node)) { + dev_dbg(pispbe->dev, +@@ -1211,7 +1246,7 @@ static int pispbe_node_s_fmt_vid_cap(str + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + int ret; + + ret = pispbe_node_try_fmt_vid_cap(file, priv, f); +@@ -1234,7 +1269,7 @@ static int pispbe_node_s_fmt_vid_out(str + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + int ret; + + ret = pispbe_node_try_fmt_vid_out(file, priv, f); +@@ -1257,7 +1292,7 @@ static int pispbe_node_s_fmt_meta_out(st + struct v4l2_format *f) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + int ret; + + ret = pispbe_node_try_fmt_meta_out(file, priv, f); +@@ -1306,7 +1341,7 @@ static int pispbe_enum_framesizes(struct + struct v4l2_frmsizeenum *fsize) + { + struct pispbe_node *node = video_drvdata(file); +- struct pispbe_dev *pispbe = node->pispbe; ++ struct pispbe_dev *pispbe = node->node_group->pispbe; + + if (NODE_IS_META(node) || fsize->index) + return -EINVAL; +@@ -1391,17 +1426,19 @@ static void pispbe_node_def_fmt(struct p + * Initialise a struct pispbe_node and register it as /dev/video + * to represent one of the PiSP Back End's input or output streams. + */ +-static int pispbe_init_node(struct pispbe_dev *pispbe, unsigned int id) ++static int pispbe_init_node(struct pispbe_node_group *node_group, ++ unsigned int id) + { + bool output = NODE_DESC_IS_OUTPUT(&node_desc[id]); +- struct pispbe_node *node = &pispbe->node[id]; ++ struct pispbe_node *node = &node_group->node[id]; + struct media_entity *entity = &node->vfd.entity; ++ struct pispbe_dev *pispbe = node_group->pispbe; + struct video_device *vdev = &node->vfd; + struct vb2_queue *q = &node->queue; + int ret; + + node->id = id; +- node->pispbe = pispbe; ++ node->node_group = node_group; + node->buf_type = node_desc[id].buf_type; + + mutex_init(&node->node_lock); +@@ -1419,7 +1456,7 @@ static int pispbe_init_node(struct pispb + q->ops = &pispbe_node_queue_ops; + q->buf_struct_size = sizeof(struct pispbe_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; +- q->dev = pispbe->dev; ++ q->dev = node->node_group->pispbe->dev; + /* get V4L2 to handle node->queue locking */ + q->lock = &node->queue_lock; + +@@ -1431,7 +1468,7 @@ static int pispbe_init_node(struct pispb + + *vdev = pispbe_videodev; /* default initialization */ + strscpy(vdev->name, node_desc[id].ent_name, sizeof(vdev->name)); +- vdev->v4l2_dev = &pispbe->v4l2_dev; ++ vdev->v4l2_dev = &node_group->v4l2_dev; + vdev->vfl_dir = output ? VFL_DIR_TX : VFL_DIR_RX; + /* get V4L2 to serialise our ioctls */ + vdev->lock = &node->node_lock; +@@ -1457,11 +1494,11 @@ static int pispbe_init_node(struct pispb + video_set_drvdata(vdev, node); + + if (output) +- ret = media_create_pad_link(entity, 0, &pispbe->sd.entity, ++ ret = media_create_pad_link(entity, 0, &node_group->sd.entity, + id, MEDIA_LNK_FL_IMMUTABLE | + MEDIA_LNK_FL_ENABLED); + else +- ret = media_create_pad_link(&pispbe->sd.entity, id, entity, ++ ret = media_create_pad_link(&node_group->sd.entity, id, entity, + 0, MEDIA_LNK_FL_IMMUTABLE | + MEDIA_LNK_FL_ENABLED); + if (ret) +@@ -1490,9 +1527,10 @@ static const struct v4l2_subdev_ops pisp + .pad = &pispbe_pad_ops, + }; + +-static int pispbe_init_subdev(struct pispbe_dev *pispbe) ++static int pispbe_init_subdev(struct pispbe_node_group *node_group) + { +- struct v4l2_subdev *sd = &pispbe->sd; ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ struct v4l2_subdev *sd = &node_group->sd; + int ret; + + v4l2_subdev_init(sd, &pispbe_sd_ops); +@@ -1502,16 +1540,16 @@ static int pispbe_init_subdev(struct pis + strscpy(sd->name, PISPBE_NAME, sizeof(sd->name)); + + for (unsigned int i = 0; i < PISPBE_NUM_NODES; i++) +- pispbe->pad[i].flags = ++ node_group->pad[i].flags = + NODE_DESC_IS_OUTPUT(&node_desc[i]) ? + MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&sd->entity, PISPBE_NUM_NODES, +- pispbe->pad); ++ node_group->pad); + if (ret) + goto error; + +- ret = v4l2_device_register_subdev(&pispbe->v4l2_dev, sd); ++ ret = v4l2_device_register_subdev(&node_group->v4l2_dev, sd); + if (ret) + goto error; + +@@ -1522,36 +1560,43 @@ error: + return ret; + } + +-static int pispbe_init_devices(struct pispbe_dev *pispbe) ++static int pispbe_init_group(struct pispbe_dev *pispbe, unsigned int id) + { ++ struct pispbe_node_group *node_group = &pispbe->node_group[id]; + struct v4l2_device *v4l2_dev; + struct media_device *mdev; + unsigned int num_regist; + int ret; + ++ node_group->id = id; ++ node_group->pispbe = pispbe; ++ node_group->streaming_map = 0; ++ ++ dev_dbg(pispbe->dev, "Register nodes for group %u\n", id); ++ + /* Register v4l2_device and media_device */ +- mdev = &pispbe->mdev; +- mdev->hw_revision = pispbe->hw_version; +- mdev->dev = pispbe->dev; ++ mdev = &node_group->mdev; ++ mdev->hw_revision = node_group->pispbe->hw_version; ++ mdev->dev = node_group->pispbe->dev; + strscpy(mdev->model, PISPBE_NAME, sizeof(mdev->model)); + media_device_init(mdev); + +- v4l2_dev = &pispbe->v4l2_dev; +- v4l2_dev->mdev = &pispbe->mdev; ++ v4l2_dev = &node_group->v4l2_dev; ++ v4l2_dev->mdev = &node_group->mdev; + strscpy(v4l2_dev->name, PISPBE_NAME, sizeof(v4l2_dev->name)); + +- ret = v4l2_device_register(pispbe->dev, v4l2_dev); ++ ret = v4l2_device_register(pispbe->dev, &node_group->v4l2_dev); + if (ret) + goto err_media_dev_cleanup; + + /* Register the PISPBE subdevice. */ +- ret = pispbe_init_subdev(pispbe); ++ ret = pispbe_init_subdev(node_group); + if (ret) + goto err_unregister_v4l2; + + /* Create device video nodes */ + for (num_regist = 0; num_regist < PISPBE_NUM_NODES; num_regist++) { +- ret = pispbe_init_node(pispbe, num_regist); ++ ret = pispbe_init_node(node_group, num_regist); + if (ret) + goto err_unregister_nodes; + } +@@ -1560,12 +1605,12 @@ static int pispbe_init_devices(struct pi + if (ret) + goto err_unregister_nodes; + +- pispbe->config = ++ node_group->config = + dma_alloc_coherent(pispbe->dev, + sizeof(struct pisp_be_tiles_config) * + PISP_BE_NUM_CONFIG_BUFFERS, +- &pispbe->config_dma_addr, GFP_KERNEL); +- if (!pispbe->config) { ++ &node_group->config_dma_addr, GFP_KERNEL); ++ if (!node_group->config) { + dev_err(pispbe->dev, "Unable to allocate cached config buffers.\n"); + ret = -ENOMEM; + goto err_unregister_mdev; +@@ -1577,11 +1622,11 @@ err_unregister_mdev: + media_device_unregister(mdev); + err_unregister_nodes: + while (num_regist-- > 0) { +- video_unregister_device(&pispbe->node[num_regist].vfd); +- vb2_queue_release(&pispbe->node[num_regist].queue); ++ video_unregister_device(&node_group->node[num_regist].vfd); ++ vb2_queue_release(&node_group->node[num_regist].queue); + } +- v4l2_device_unregister_subdev(&pispbe->sd); +- media_entity_cleanup(&pispbe->sd.entity); ++ v4l2_device_unregister_subdev(&node_group->sd); ++ media_entity_cleanup(&node_group->sd.entity); + err_unregister_v4l2: + v4l2_device_unregister(v4l2_dev); + err_media_dev_cleanup: +@@ -1589,31 +1634,33 @@ err_media_dev_cleanup: + return ret; + } + +-static void pispbe_destroy_devices(struct pispbe_dev *pispbe) ++static void pispbe_destroy_node_group(struct pispbe_node_group *node_group) + { +- if (pispbe->config) { +- dma_free_coherent(pispbe->dev, ++ struct pispbe_dev *pispbe = node_group->pispbe; ++ ++ if (node_group->config) { ++ dma_free_coherent(node_group->pispbe->dev, + sizeof(struct pisp_be_tiles_config) * + PISP_BE_NUM_CONFIG_BUFFERS, +- pispbe->config, +- pispbe->config_dma_addr); ++ node_group->config, ++ node_group->config_dma_addr); + } + + dev_dbg(pispbe->dev, "Unregister from media controller\n"); + +- v4l2_device_unregister_subdev(&pispbe->sd); +- media_entity_cleanup(&pispbe->sd.entity); +- media_device_unregister(&pispbe->mdev); ++ v4l2_device_unregister_subdev(&node_group->sd); ++ media_entity_cleanup(&node_group->sd.entity); ++ media_device_unregister(&node_group->mdev); + + for (int i = PISPBE_NUM_NODES - 1; i >= 0; i--) { +- video_unregister_device(&pispbe->node[i].vfd); +- vb2_queue_release(&pispbe->node[i].queue); +- mutex_destroy(&pispbe->node[i].node_lock); +- mutex_destroy(&pispbe->node[i].queue_lock); ++ video_unregister_device(&node_group->node[i].vfd); ++ vb2_queue_release(&node_group->node[i].queue); ++ mutex_destroy(&node_group->node[i].node_lock); ++ mutex_destroy(&node_group->node[i].queue_lock); + } + +- media_device_cleanup(&pispbe->mdev); +- v4l2_device_unregister(&pispbe->v4l2_dev); ++ media_device_cleanup(&node_group->mdev); ++ v4l2_device_unregister(&node_group->v4l2_dev); + } + + static int pispbe_runtime_suspend(struct device *dev) +@@ -1681,9 +1728,13 @@ static int pispbe_hw_init(struct pispbe_ + return 0; + } + +-/* Probe the ISP-BE hardware block, as a single platform device. */ ++/* ++ * Probe the ISP-BE hardware block, as a single platform device. ++ * This will instantiate multiple "node groups" each with many device nodes. ++ */ + static int pispbe_probe(struct platform_device *pdev) + { ++ unsigned int num_groups = 0; + struct pispbe_dev *pispbe; + int ret; + +@@ -1738,17 +1789,26 @@ static int pispbe_probe(struct platform_ + if (ret) + goto pm_runtime_suspend_err; + +- ret = pispbe_init_devices(pispbe); +- if (ret) +- goto disable_devs_err; ++ /* ++ * Initialise and register devices for each node_group, including media ++ * device ++ */ ++ for (num_groups = 0; ++ num_groups < PISPBE_NUM_NODE_GROUPS; ++ num_groups++) { ++ ret = pispbe_init_group(pispbe, num_groups); ++ if (ret) ++ goto disable_nodes_err; ++ } + + pm_runtime_mark_last_busy(pispbe->dev); + pm_runtime_put_autosuspend(pispbe->dev); + + return 0; + +-disable_devs_err: +- pispbe_destroy_devices(pispbe); ++disable_nodes_err: ++ while (num_groups-- > 0) ++ pispbe_destroy_node_group(&pispbe->node_group[num_groups]); + pm_runtime_suspend_err: + pispbe_runtime_suspend(pispbe->dev); + pm_runtime_disable_err: +@@ -1762,7 +1822,8 @@ static int pispbe_remove(struct platform + { + struct pispbe_dev *pispbe = platform_get_drvdata(pdev); + +- pispbe_destroy_devices(pispbe); ++ for (int i = PISPBE_NUM_NODE_GROUPS - 1; i >= 0; i--) ++ pispbe_destroy_node_group(&pispbe->node_group[i]); + + pispbe_runtime_suspend(pispbe->dev); + pm_runtime_dont_use_autosuspend(pispbe->dev); diff --git a/target/linux/bcm27xx/patches-6.6/950-1161-media-pisp_be-Re-introduce-video-node-offset.patch b/target/linux/bcm27xx/patches-6.6/950-1161-media-pisp_be-Re-introduce-video-node-offset.patch new file mode 100644 index 0000000000..0586f5c620 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1161-media-pisp_be-Re-introduce-video-node-offset.patch @@ -0,0 +1,36 @@ +From f372f2854279828a33b9b3debc233d366fb4c124 Mon Sep 17 00:00:00 2001 +From: Naushir Patuck +Date: Mon, 8 Jul 2024 11:47:49 +0100 +Subject: [PATCH 1161/1215] media: pisp_be: Re-introduce video node offset + +Offset the backend dev-nodes starting at /dev/video20 +onwards to maintain backward compatibility with the +pre-upstreamed kernel driver. + +Signed-off-by: Naushir Patuck +--- + drivers/media/platform/raspberrypi/pisp_be/pisp_be.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c ++++ b/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c +@@ -21,6 +21,9 @@ + + #include "pisp_be_formats.h" + ++/* Offset to use when registering the /dev/videoX node */ ++#define PISPBE_VIDEO_NODE_OFFSET 20 ++ + /* Maximum number of config buffers possible */ + #define PISP_BE_NUM_CONFIG_BUFFERS VB2_MAX_FRAME + +@@ -1484,7 +1487,8 @@ static int pispbe_init_node(struct pispb + goto err_unregister_queue; + } + +- ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); ++ ret = video_register_device(vdev, VFL_TYPE_VIDEO, ++ PISPBE_VIDEO_NODE_OFFSET); + if (ret) { + dev_err(pispbe->dev, + "Failed to register video %s device node\n", diff --git a/target/linux/bcm27xx/patches-6.6/950-1163-dts-Make-camN_reg-and-camN_reg_gpio-overrides-generi.patch b/target/linux/bcm27xx/patches-6.6/950-1163-dts-Make-camN_reg-and-camN_reg_gpio-overrides-generi.patch new file mode 100644 index 0000000000..38c1d3b9b6 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1163-dts-Make-camN_reg-and-camN_reg_gpio-overrides-generi.patch @@ -0,0 +1,158 @@ +From 6e4ad40811170653431fc40a6fdc3f486863b40f Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 4 Jul 2024 18:15:00 +0100 +Subject: [PATCH 1163/1215] dts: Make camN_reg and camN_reg_gpio overrides + generic + +The camera regulator GPIO can be used for other purposes, +so the camN_reg override to allow disabling is potentially +useful on any platform. +camN_gpio is less useful, but isn't invalid. + +Move these overrides from the CM dt files to bcm270x-rpi.dtsi +and bcm2712-rpi.dtsi. + +Signed-off-by: Dave Stevenson +--- + .../arm/boot/dts/broadcom/bcm2708-rpi-cm.dtsi | 4 ---- + .../arm/boot/dts/broadcom/bcm2709-rpi-cm2.dts | 4 ---- + arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi | 7 +++++++ + .../arm/boot/dts/broadcom/bcm2710-rpi-cm3.dts | 4 ---- + .../arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts | 7 ------- + .../boot/dts/broadcom/bcm2711-rpi-cm4s.dts | 5 ----- + arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi | 8 ++++++++ + arch/arm/boot/dts/overlays/README | 20 +++++++++---------- + 8 files changed, 25 insertions(+), 34 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm2708-rpi-cm.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm2708-rpi-cm.dtsi +@@ -19,9 +19,5 @@ i2c_vc: &i2c0 { + act_led_gpio = <&led_act>,"gpios:4"; + act_led_activelow = <&led_act>,"gpios:8"; + act_led_trigger = <&led_act>,"linux,default-trigger"; +- cam0_reg = <&cam0_reg>,"status"; +- cam0_reg_gpio = <&cam0_reg>,"gpio:4"; +- cam1_reg = <&cam1_reg>,"status"; +- cam1_reg_gpio = <&cam1_reg>,"gpio:4"; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm2709-rpi-cm2.dts ++++ b/arch/arm/boot/dts/broadcom/bcm2709-rpi-cm2.dts +@@ -211,9 +211,5 @@ i2c_csi_dsi0: &i2c0 { + act_led_gpio = <&led_act>,"gpios:4"; + act_led_activelow = <&led_act>,"gpios:8"; + act_led_trigger = <&led_act>,"linux,default-trigger"; +- cam0_reg = <&cam0_reg>,"status"; +- cam0_reg_gpio = <&cam0_reg>,"gpio:4"; +- cam1_reg = <&cam1_reg>,"status"; +- cam1_reg_gpio = <&cam1_reg>,"gpio:4"; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm270x-rpi.dtsi +@@ -111,6 +111,13 @@ + <&csi0>, "sync-gpios:4", + <&csi0>, "sync-gpios:8=", ; + ++ cam0_reg = <&cam0_reg>,"status"; ++ cam0_reg_gpio = <&cam0_reg>,"gpio:4", ++ <&cam0_reg>,"gpio:0=", <&gpio>; ++ cam1_reg = <&cam1_reg>,"status"; ++ cam1_reg_gpio = <&cam1_reg>,"gpio:4", ++ <&cam1_reg>,"gpio:0=", <&gpio>; ++ + strict_gpiod = <&chosen>, "bootargs=pinctrl_bcm2835.persist_gpio_outputs=n"; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm2710-rpi-cm3.dts ++++ b/arch/arm/boot/dts/broadcom/bcm2710-rpi-cm3.dts +@@ -211,9 +211,5 @@ i2c_csi_dsi0: &i2c0 { + act_led_gpio = <&led_act>,"gpios:4"; + act_led_activelow = <&led_act>,"gpios:8"; + act_led_trigger = <&led_act>,"linux,default-trigger"; +- cam0_reg = <&cam0_reg>,"status"; +- cam0_reg_gpio = <&cam0_reg>,"gpio:4"; +- cam1_reg = <&cam1_reg>,"status"; +- cam1_reg_gpio = <&cam1_reg>,"gpio:4"; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts ++++ b/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4.dts +@@ -498,13 +498,6 @@ i2c_csi_dsi0: &i2c0 { + <&ant2>, "output-high?=off", + <&ant2>, "output-low?=on"; + +- cam0_reg = <&cam0_reg>,"status"; +- cam0_reg_gpio = <&cam0_reg>,"gpio:4", +- <&cam0_reg>,"gpio:0=", <&gpio>; +- cam1_reg = <&cam1_reg>,"status"; +- cam1_reg_gpio = <&cam1_reg>,"gpio:4", +- <&cam1_reg>,"gpio:0=", <&gpio>; +- + pcie_tperst_clk_ms = <&pcie0>,"brcm,tperst-clk-ms:0"; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4s.dts ++++ b/arch/arm/boot/dts/broadcom/bcm2711-rpi-cm4s.dts +@@ -289,10 +289,5 @@ i2c_csi_dsi0: &i2c0 { + act_led_gpio = <&led_act>,"gpios:4"; + act_led_activelow = <&led_act>,"gpios:8"; + act_led_trigger = <&led_act>,"linux,default-trigger"; +- +- cam0_reg = <&cam0_reg>,"status"; +- cam0_reg_gpio = <&cam0_reg>,"gpio:4"; +- cam1_reg = <&cam1_reg>,"status"; +- cam1_reg_gpio = <&cam1_reg>,"gpio:4"; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi +@@ -106,6 +106,14 @@ + nvmem_priv_rw = <&nvmem_priv>,"rw?"; + nvmem_mac_rw = <&nvmem_mac>,"rw?"; + strict_gpiod = <&chosen>, "bootargs=pinctrl_rp1.persist_gpio_outputs=n"; ++ ++ cam0_reg = <&cam0_reg>,"status"; ++ cam0_reg_gpio = <&cam0_reg>,"gpio:4", ++ <&cam0_reg>,"gpio:0=", <&gpio>; ++ cam1_reg = <&cam1_reg>,"status"; ++ cam1_reg_gpio = <&cam1_reg>,"gpio:4", ++ <&cam1_reg>,"gpio:0=", <&gpio>; ++ + }; + }; + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -171,21 +171,21 @@ Params: + button_debounce Set the debounce delay (in ms) on the power/ + shutdown button (default 50ms) + +- cam0_reg Enables CAM 0 regulator. +- Only required on CM1 & 3. ++ cam0_reg Controls CAM 0 regulator. ++ Disabled by default on CM1 & 3. ++ Enabled by default on all other boards. + + cam0_reg_gpio Set GPIO for CAM 0 regulator. +- Default 31 on CM1, 3, and 4S. +- Default of GPIO expander 5 on CM4, but override +- switches to normal GPIO. ++ NB override switches to the normal GPIO driver, ++ even if the original was on the GPIO expander. + +- cam1_reg Enables CAM 1 regulator. +- Only required on CM1 & 3. ++ cam1_reg Controls CAM 1 regulator. ++ Disabled by default on CM1 & 3. ++ Enabled by default on all other boards. + + cam1_reg_gpio Set GPIO for CAM 1 regulator. +- Default 3 on CM1, 3, and 4S. +- Default of GPIO expander 5 on CM4, but override +- switches to normal GPIO. ++ NB override switches to the normal GPIO driver, ++ even if the original was on the GPIO expander. + + cam0_sync Enable a GPIO to reflect frame sync from CSI0, + going high on frame start, and low on frame end. diff --git a/target/linux/bcm27xx/patches-6.6/950-1164-spi-dt-bindings-Add-RPI-RP2040-GPIO-Bridge.patch b/target/linux/bcm27xx/patches-6.6/950-1164-spi-dt-bindings-Add-RPI-RP2040-GPIO-Bridge.patch new file mode 100644 index 0000000000..487e508ea4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1164-spi-dt-bindings-Add-RPI-RP2040-GPIO-Bridge.patch @@ -0,0 +1,108 @@ +From afd949f5f64d224cf7a016ef933257842bc170ab Mon Sep 17 00:00:00 2001 +From: Richard Oliver +Date: Fri, 24 May 2024 10:34:45 +0100 +Subject: [PATCH 1164/1215] spi: dt-bindings: Add RPI RP2040 GPIO Bridge + +Add YAML device tree bindings for the Raspberry Pi RP2040 GPIO Bridge. + +Signed-off-by: Richard Oliver +--- + .../spi/raspberrypi,rp2040-gpio-bridge.yaml | 77 +++++++++++++++++++ + MAINTAINERS | 5 ++ + 2 files changed, 82 insertions(+) + create mode 100644 Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml +@@ -0,0 +1,77 @@ ++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/spi/raspberrypi,rp2040-gpio-bridge.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Raspberry Pi RP2040 GPIO Bridge ++ ++maintainers: ++ - Raspberry Pi ++ ++description: |- ++ The Raspberry Pi PR2040 GPIO bridge can be used as a GPIO expander and ++ Tx-only SPI master. ++ ++properties: ++ reg: ++ description: I2C slave address ++ const: 0x40 ++ ++ compatible: ++ const: raspberrypi,rp2040-gpio-bridge ++ ++ power-supply: ++ description: Phandle to the regulator that powers the RP2040. ++ ++ '#address-cells': ++ const: 1 ++ ++ '#size-cells': ++ const: 0 ++ ++ '#gpio-cells': ++ const: 2 ++ ++ gpio-controller: true ++ ++ fast_xfer_requires_i2c_lock: ++ description: Set if I2C bus should be locked during fast transfer. ++ ++ fast_xfer_recv_gpio_base: ++ description: RP2040 GPIO base for fast transfer pair. ++ ++ fast_xfer-gpios: ++ description: RP1 GPIOs to use for fast transfer clock and data. ++ ++required: ++ - reg ++ - compatible ++ - power-supply ++ - '#gpio-cells' ++ - gpio-controller ++ ++additionalProperties: false ++ ++examples: ++ - | ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ spi@40 { ++ reg = <0x40>; ++ compatible = "raspberrypi,rp2040-gpio-bridge"; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ power-supply = <&cam_dummy_reg>; ++ ++ #gpio-cells = <2>; ++ gpio-controller; ++ }; ++ }; ++ ++... ++ +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -18027,6 +18027,11 @@ F: drivers/ras/ + F: include/linux/ras.h + F: include/ras/ras_event.h + ++RASPBERRY PI RP2040 GPIO BRIDGE DRIVER ++M: Raspberry Pi Kernel Maintenance ++S: Maintained ++F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml ++ + RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER + L: linux-wireless@vger.kernel.org + S: Orphan diff --git a/target/linux/bcm27xx/patches-6.6/950-1165-spi-Add-a-driver-for-the-RPI-RP2040-GPIO-bridge.patch b/target/linux/bcm27xx/patches-6.6/950-1165-spi-Add-a-driver-for-the-RPI-RP2040-GPIO-bridge.patch new file mode 100644 index 0000000000..68e2ef6007 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1165-spi-Add-a-driver-for-the-RPI-RP2040-GPIO-bridge.patch @@ -0,0 +1,1288 @@ +From 99ae83f1944f47d4338ef7a6f02536927fc6ce57 Mon Sep 17 00:00:00 2001 +From: Richard Oliver +Date: Tue, 21 May 2024 13:47:23 +0100 +Subject: [PATCH 1165/1215] spi: Add a driver for the RPI RP2040 GPIO bridge + +The Raspberry Pi RP2040 GPIO bridge is an I2C-attached device exposing +both a Tx-only SPI controller, and a GPIO controller. + +Due to the relative difference in transfer rates between standard-mode +I2C and SPI, the GPIO bridge makes use of 12 MiB of non-volatile storage +to cache repeated transfers. This cache is arranged in ~8 KiB blocks and +is addressed by the MD5 digest of the data contained therein. + +Optionally, this driver is able to take advantage of Raspberry Pi RP1 +GPIOs to achieve faster than I2C data transfer rates. + +Signed-off-by: Richard Oliver +--- + MAINTAINERS | 1 + + drivers/spi/Kconfig | 12 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-rp2040-gpio-bridge.c | 1219 ++++++++++++++++++++++++++ + 4 files changed, 1233 insertions(+) + create mode 100644 drivers/spi/spi-rp2040-gpio-bridge.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -18031,6 +18031,7 @@ RASPBERRY PI RP2040 GPIO BRIDGE DRIVER + M: Raspberry Pi Kernel Maintenance + S: Maintained + F: Documentation/devicetree/bindings/spi/raspberrypi,rp2040-gpio-bridge.yaml ++F: drivers/spi/spi-rp2040-gpio-bridge.c + + RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER + L: linux-wireless@vger.kernel.org +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -846,6 +846,18 @@ config SPI_RB4XX + help + SPI controller driver for the Mikrotik RB4xx series boards. + ++config SPI_RP2040_GPIO_BRIDGE ++ tristate "Raspberry Pi RP2040 GPIO Bridge" ++ depends on I2C && SPI && GPIOLIB ++ help ++ Support for the Raspberry Pi RP2040 GPIO bridge. ++ ++ This driver provides support for the Raspberry Pi PR2040 GPIO bridge. ++ It can be used as a GPIO expander and a Tx-only SPI master. ++ ++ Optionally, this driver is able to take advantage of Raspberry Pi RP1 ++ GPIOs to achieve faster than I2C data transfer rates. ++ + config SPI_RPCIF + tristate "Renesas RPC-IF SPI driver" + depends on RENESAS_RPCIF +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -115,6 +115,7 @@ obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockc + obj-$(CONFIG_SPI_ROCKCHIP_SFC) += spi-rockchip-sfc.o + obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o + obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o ++obj-$(CONFIG_SPI_RP2040_GPIO_BRIDGE) += spi-rp2040-gpio-bridge.o + obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o + obj-$(CONFIG_SPI_RSPI) += spi-rspi.o + obj-$(CONFIG_SPI_RZV2M_CSI) += spi-rzv2m-csi.o +--- /dev/null ++++ b/drivers/spi/spi-rp2040-gpio-bridge.c +@@ -0,0 +1,1219 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * RP2040 GPIO Bridge ++ * ++ * Copyright (C) 2023, 2024, Raspberry Pi Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MODULE_NAME "rp2040-gpio-bridge" ++ ++#define I2C_RETRIES 4U ++ ++#define ONE_KIB 1024U ++#define MD5_SUFFIX_SIZE 9U ++ ++#define RP2040_GBDG_FLASH_BLOCK_SIZE (8U * ONE_KIB) ++#define RP2040_GBDG_BLOCK_SIZE (RP2040_GBDG_FLASH_BLOCK_SIZE - MD5_SUFFIX_SIZE) ++ ++/* ++ * 1MiB transfer size is an arbitrary limit ++ * Max value is 4173330 (using a single manifest) ++ */ ++#define MAX_TRANSFER_SIZE (1024U * ONE_KIB) ++ ++#define HALF_BUFFER (4U * ONE_KIB) ++ ++#define STATUS_SIZE 4 ++#define MD5_DIGEST_SIZE 16 ++#define VERSION_SIZE 4 ++#define ID_SIZE 8 ++#define TOTAL_RD_HDR_SIZE \ ++ (STATUS_SIZE + MD5_DIGEST_SIZE + VERSION_SIZE + ID_SIZE) ++ ++struct rp2040_gbdg_device_info { ++ u8 md5[MD5_DIGEST_SIZE]; ++ u64 id; ++ u32 version; ++ u32 status; ++}; ++ ++static_assert(sizeof(struct rp2040_gbdg_device_info) == TOTAL_RD_HDR_SIZE); ++ ++#define MANIFEST_UNIT_SIZE 16 ++static_assert(MD5_DIGEST_SIZE == MANIFEST_UNIT_SIZE); ++#define MANIFEST_HEADER_UNITS 1 ++#define MANIFEST_DATA_UNITS \ ++ DIV_ROUND_UP(MAX_TRANSFER_SIZE, RP2040_GBDG_BLOCK_SIZE) ++ ++#define STATUS_BUSY 0x01 ++ ++#define DIRECT_PREFIX 0x00 ++#define DIRECT_CMD_CS 0x07 ++#define DIRECT_CMD_EMIT 0x08 ++ ++#define WRITE_DATA_PREFIX 0x80 ++#define WRITE_DATA_PREFIX_SIZE 1 ++ ++#define FIXED_SIZE_CMD_PREFIX 0x81 ++ ++#define WRITE_DATA_UPPER_PREFIX 0x82 ++#define WRITE_DATA_UPPER_PREFIX_SIZE 1 ++ ++#define NUM_GPIO 24 ++ ++enum rp2040_gbdg_fixed_size_commands { ++ /* 10-byte commands */ ++ CMD_SAVE_CACHE = 0x07, ++ CMD_SEND_RB = 0x08, ++ CMD_GPIO_ST_CL = 0x0b, ++ CMD_GPIO_OE = 0x0c, ++ CMD_DAT_RECV = 0x0d, ++ CMD_DAT_EMIT = 0x0e, ++ /* 18-byte commands */ ++ CMD_READ_CSUM = 0x11, ++ CMD_SEND_MANI = 0x13, ++}; ++ ++struct rp2040_gbdg { ++ struct spi_controller *controller; ++ ++ struct i2c_client *client; ++ struct crypto_shash *shash; ++ struct shash_desc *shash_desc; ++ ++ struct regulator *regulator; ++ ++ struct gpio_chip gc; ++ u32 gpio_requested; ++ u32 gpio_direction; ++ ++ bool fast_xfer_requires_i2c_lock; ++ struct gpio_descs *fast_xfer_gpios; ++ u32 fast_xfer_recv_gpio_base; ++ u8 fast_xfer_data_index; ++ u8 fast_xfer_clock_index; ++ void __iomem *gpio_base; ++ void __iomem *rio_base; ++ ++ bool bypass_cache; ++ ++ u8 buffer[2 + HALF_BUFFER]; ++ u8 manifest_prep[(MANIFEST_HEADER_UNITS + MANIFEST_DATA_UNITS) * ++ MANIFEST_UNIT_SIZE]; ++}; ++ ++static int rp2040_gbdg_gpio_dir_in(struct gpio_chip *gc, unsigned int offset); ++static void rp2040_gbdg_gpio_set(struct gpio_chip *gc, unsigned int offset, ++ int value); ++static int rp2040_gbdg_fast_xfer(struct rp2040_gbdg *priv_data, const u8 *data, ++ size_t len); ++ ++static int rp2040_gbdg_rp1_calc_offsets(u8 gpio, size_t *bank_offset, ++ u8 *shift_offset) ++{ ++ if (!bank_offset || !shift_offset || gpio >= 54) ++ return -EINVAL; ++ if (gpio < 28) { ++ *bank_offset = 0x0000; ++ *shift_offset = gpio; ++ } else if (gpio < 34) { ++ *bank_offset = 0x4000; ++ *shift_offset = gpio - 28; ++ } else { ++ *bank_offset = 0x8000; ++ *shift_offset = gpio - 34; ++ } ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_calc_mux_offset(u8 gpio, size_t *offset) ++{ ++ size_t bank_offset; ++ u8 shift_offset; ++ int ret; ++ ++ ret = rp2040_gbdg_rp1_calc_offsets(gpio, &bank_offset, &shift_offset); ++ if (ret) ++ return ret; ++ *offset = bank_offset + shift_offset * 8 + 0x4; ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_rp1_read_mux(struct rp2040_gbdg *priv_data, u8 gpio, ++ u32 *data) ++{ ++ size_t offset; ++ int ret; ++ ++ ret = rp2040_gbdg_calc_mux_offset(gpio, &offset); ++ if (ret) ++ return ret; ++ ++ *data = readl(priv_data->gpio_base + offset); ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_rp1_write_mux(struct rp2040_gbdg *priv_data, u8 gpio, ++ u32 val) ++{ ++ size_t offset; ++ int ret; ++ ++ ret = rp2040_gbdg_calc_mux_offset(gpio, &offset); ++ if (ret) ++ return ret; ++ ++ writel(val, priv_data->gpio_base + offset); ++ ++ return 0; ++} ++ ++static size_t rp2040_gbdg_max_transfer_size(struct spi_device *spi) ++{ ++ return MAX_TRANSFER_SIZE; ++} ++ ++static int rp2040_gbdg_get_device_info(struct i2c_client *client, ++ struct rp2040_gbdg_device_info *info) ++{ ++ u8 buf[TOTAL_RD_HDR_SIZE]; ++ u8 retries = I2C_RETRIES; ++ u8 *read_pos = buf; ++ size_t field_size; ++ int ret; ++ ++ do { ++ ret = i2c_master_recv(client, buf, sizeof(buf)); ++ if (!retries--) ++ break; ++ } while (ret == -ETIMEDOUT); ++ ++ if (ret != sizeof(buf)) ++ return ret < 0 ? ret : -EIO; ++ ++ field_size = sizeof_field(struct rp2040_gbdg_device_info, status); ++ memcpy(&info->status, read_pos, field_size); ++ read_pos += field_size; ++ ++ field_size = sizeof_field(struct rp2040_gbdg_device_info, md5); ++ memcpy(&info->md5, read_pos, field_size); ++ read_pos += field_size; ++ ++ field_size = sizeof_field(struct rp2040_gbdg_device_info, version); ++ memcpy(&info->version, read_pos, field_size); ++ read_pos += field_size; ++ ++ field_size = sizeof_field(struct rp2040_gbdg_device_info, id); ++ memcpy(&info->id, read_pos, field_size); ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_poll_device_info(struct i2c_client *client, ++ struct rp2040_gbdg_device_info *info) ++{ ++ struct rp2040_gbdg_device_info itnl; ++ int ret; ++ ++ itnl.status = STATUS_BUSY; ++ ++ while (itnl.status & STATUS_BUSY) { ++ ret = rp2040_gbdg_get_device_info(client, &itnl); ++ if (ret) ++ return ret; ++ } ++ memcpy(info, &itnl, sizeof(itnl)); ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_get_buffer_hash(struct i2c_client *client, u8 *md5) ++{ ++ struct rp2040_gbdg_device_info info; ++ int ret; ++ ++ ret = rp2040_gbdg_poll_device_info(client, &info); ++ if (ret) ++ return ret; ++ ++ memcpy(md5, info.md5, MD5_DIGEST_SIZE); ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_wait_until_free(struct i2c_client *client, u8 *status) ++{ ++ struct rp2040_gbdg_device_info info; ++ int ret; ++ ++ ret = rp2040_gbdg_poll_device_info(client, &info); ++ if (ret) ++ return ret; ++ ++ if (status) ++ *status = info.status; ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_i2c_send(struct i2c_client *client, const u8 *buf, ++ size_t len) ++{ ++ u8 retries = I2C_RETRIES; ++ int ret; ++ ++ ret = rp2040_gbdg_wait_until_free(client, NULL); ++ if (ret) { ++ dev_err(&client->dev, ++ "%s() rp2040_gbdg_wait_until_free failed\n", __func__); ++ return ret; ++ } ++ ++ do { ++ ret = i2c_master_send(client, buf, len); ++ if (!retries--) ++ break; ++ } while (ret == -ETIMEDOUT); ++ ++ if (ret != len) { ++ dev_err(&client->dev, "%s() i2c_master_send returned %d\n", ++ __func__, ret); ++ return ret < 0 ? ret : -EIO; ++ } ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_10byte_cmd(struct i2c_client *client, u8 cmd, u32 addr, ++ u32 len) ++{ ++ u8 buffer[10]; ++ ++ buffer[0] = FIXED_SIZE_CMD_PREFIX; ++ buffer[1] = cmd; ++ memcpy(&buffer[2], &addr, sizeof(addr)); ++ memcpy(&buffer[6], &len, sizeof(len)); ++ ++ return rp2040_gbdg_i2c_send(client, buffer, sizeof(buffer)); ++} ++ ++static int rp2040_gbdg_18byte_cmd(struct i2c_client *client, u8 cmd, ++ const u8 *digest) ++{ ++ u8 buffer[18]; ++ ++ buffer[0] = FIXED_SIZE_CMD_PREFIX; ++ buffer[1] = cmd; ++ memcpy(&buffer[2], digest, MD5_DIGEST_SIZE); ++ ++ return rp2040_gbdg_i2c_send(client, buffer, sizeof(buffer)); ++} ++ ++static int rp2040_gbdg_block_hash(struct rp2040_gbdg *priv_data, const u8 *data, ++ size_t len, u8 *out) ++{ ++ size_t remaining = RP2040_GBDG_BLOCK_SIZE; ++ size_t pad; ++ int ret; ++ ++ static const u8 padding[64] = { ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ++ 0xFF, 0xFF, 0xFF, 0xFF, ++ }; ++ ++ if (len > RP2040_GBDG_BLOCK_SIZE) { ++ return -EMSGSIZE; ++ } else if (len == RP2040_GBDG_BLOCK_SIZE) { ++ return crypto_shash_digest(priv_data->shash_desc, data, len, ++ out); ++ } else { ++ ret = crypto_shash_init(priv_data->shash_desc); ++ if (ret) ++ return ret; ++ ++ ret = crypto_shash_update(priv_data->shash_desc, data, len); ++ if (ret) ++ return ret; ++ remaining -= len; ++ ++ /* Pad up-to a 64-byte boundary, unless that takes us over. */ ++ pad = round_up(len, 64); ++ if (pad != len && pad < RP2040_GBDG_BLOCK_SIZE) { ++ ret = crypto_shash_update(priv_data->shash_desc, ++ padding, pad - len); ++ if (ret) ++ return ret; ++ remaining -= (pad - len); ++ } ++ ++ /* Pad up-to RP2040_GBDG_BLOCK_SIZE in, preferably, 64-byte chunks */ ++ while (remaining) { ++ pad = min_t(size_t, remaining, (size_t)64U); ++ ret = crypto_shash_update(priv_data->shash_desc, ++ padding, pad); ++ if (ret) ++ return ret; ++ remaining -= pad; ++ } ++ return crypto_shash_final(priv_data->shash_desc, out); ++ } ++} ++ ++static int rp2040_gbdg_set_remote_buffer_fast(struct rp2040_gbdg *priv_data, ++ const u8 *data, unsigned int len) ++{ ++ struct i2c_client *client = priv_data->client; ++ int ret; ++ ++ if (len > RP2040_GBDG_BLOCK_SIZE) ++ return -EMSGSIZE; ++ if (!priv_data->fast_xfer_gpios) ++ return -EIO; ++ ++ ret = rp2040_gbdg_10byte_cmd(client, CMD_DAT_RECV, ++ priv_data->fast_xfer_recv_gpio_base, len); ++ if (ret) { ++ dev_err(&client->dev, "%s() failed to enter fast data mode\n", ++ __func__); ++ return ret; ++ } ++ ++ return rp2040_gbdg_fast_xfer(priv_data, data, len); ++} ++ ++static int rp2040_gbdg_set_remote_buffer_i2c(struct rp2040_gbdg *priv_data, ++ const u8 *data, unsigned int len) ++{ ++ struct i2c_client *client = priv_data->client; ++ unsigned int write_len; ++ int ret; ++ ++ if (len > RP2040_GBDG_BLOCK_SIZE) ++ return -EMSGSIZE; ++ ++ priv_data->buffer[0] = WRITE_DATA_PREFIX; ++ write_len = min(len, HALF_BUFFER); ++ memcpy(&priv_data->buffer[1], data, write_len); ++ ++ ret = rp2040_gbdg_i2c_send(client, priv_data->buffer, write_len + 1); ++ if (ret) ++ return ret; ++ ++ len -= write_len; ++ data += write_len; ++ ++ if (!len) ++ return 0; ++ ++ priv_data->buffer[0] = WRITE_DATA_UPPER_PREFIX; ++ memcpy(&priv_data->buffer[1], data, len); ++ ret = rp2040_gbdg_i2c_send(client, priv_data->buffer, len + 1); ++ ++ return ret; ++} ++ ++static int rp2040_gbdg_set_remote_buffer(struct rp2040_gbdg *priv_data, ++ const u8 *data, unsigned int len) ++{ ++ if (priv_data->fast_xfer_gpios) ++ return rp2040_gbdg_set_remote_buffer_fast(priv_data, data, len); ++ else ++ return rp2040_gbdg_set_remote_buffer_i2c(priv_data, data, len); ++} ++ ++/* Loads data by checksum if available or resorts to sending byte-by-byte */ ++static int rp2040_gbdg_load_block_remote(struct rp2040_gbdg *priv_data, ++ const void *data, unsigned int len, ++ u8 *digest, bool persist) ++{ ++ u8 ascii_digest[MD5_DIGEST_SIZE * 2 + 1] = { 0 }; ++ struct i2c_client *client = priv_data->client; ++ u8 remote_digest[MD5_DIGEST_SIZE]; ++ u8 local_digest[MD5_DIGEST_SIZE]; ++ int ret; ++ ++ if (len > RP2040_GBDG_BLOCK_SIZE) ++ return -EMSGSIZE; ++ ++ ret = rp2040_gbdg_block_hash(priv_data, data, len, local_digest); ++ if (ret) ++ return ret; ++ ++ if (digest) ++ memcpy(digest, local_digest, MD5_DIGEST_SIZE); ++ ++ /* Check if the RP2040 has the data already */ ++ ret = rp2040_gbdg_18byte_cmd(client, CMD_READ_CSUM, local_digest); ++ if (ret) ++ return ret; ++ ++ ret = rp2040_gbdg_get_buffer_hash(client, remote_digest); ++ if (ret) ++ return ret; ++ ++ if (memcmp(local_digest, remote_digest, MD5_DIGEST_SIZE)) { ++ bin2hex(ascii_digest, local_digest, MD5_DIGEST_SIZE); ++ dev_info(&client->dev, "%s() device missing data: %s\n", ++ __func__, ascii_digest); ++ /* ++ * N.B. We're fine to send (the potentially shorter) transfer->len ++ * number of bytes here as the RP2040 will pad with 0xFF up to buffer ++ * size once we stop sending. ++ */ ++ ret = rp2040_gbdg_set_remote_buffer(priv_data, data, len); ++ if (ret) ++ return ret; ++ ++ /* Make sure the data actually arrived. */ ++ ret = rp2040_gbdg_get_buffer_hash(client, remote_digest); ++ if (memcmp(local_digest, remote_digest, MD5_DIGEST_SIZE)) { ++ dev_err(&priv_data->client->dev, ++ "%s() unable to send data to device\n", ++ __func__); ++ return -EREMOTEIO; ++ } ++ ++ if (persist) { ++ dev_info(&client->dev, ++ "%s() sent missing data to device, saving\n", ++ __func__); ++ ret = rp2040_gbdg_10byte_cmd(client, CMD_SAVE_CACHE, 0, ++ 0); ++ if (ret) ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_transfer_block(struct rp2040_gbdg *priv_data, ++ const void *data, unsigned int len) ++{ ++ struct i2c_client *client = priv_data->client; ++ int ret; ++ ++ if (len > RP2040_GBDG_BLOCK_SIZE) ++ return -EMSGSIZE; ++ ++ ret = rp2040_gbdg_load_block_remote(priv_data, data, len, NULL, true); ++ if (ret) ++ return ret; ++ ++ /* Remote rambuffer now has correct contents, send it */ ++ ret = rp2040_gbdg_10byte_cmd(client, CMD_SEND_RB, 0, len); ++ if (ret) ++ return ret; ++ ++ /* ++ * Wait for data to have actually completed sending as we may be de-asserting CS too quickly ++ * otherwise. ++ */ ++ ret = rp2040_gbdg_wait_until_free(client, NULL); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_transfer_manifest(struct rp2040_gbdg *priv_data, ++ const u8 *data, unsigned int len) ++{ ++ struct i2c_client *client = priv_data->client; ++ static const char magic[] = "DATA_MANFST"; ++ unsigned int remaining = len; ++ const u32 data_length = len; ++ u8 digest[MD5_DIGEST_SIZE]; ++ u8 *digest_write_pos; ++ u8 status; ++ int ret; ++ ++ memcpy(priv_data->manifest_prep, magic, sizeof(magic)); ++ memcpy(priv_data->manifest_prep + sizeof(magic), &data_length, ++ sizeof(data_length)); ++ digest_write_pos = ++ priv_data->manifest_prep + sizeof(magic) + sizeof(data_length); ++ ++ while (remaining) { ++ unsigned int size = min(remaining, RP2040_GBDG_BLOCK_SIZE); ++ ++ ret = rp2040_gbdg_block_hash(priv_data, data, size, ++ digest_write_pos); ++ if (ret) ++ return ret; ++ ++ remaining -= size; ++ data += size; ++ digest_write_pos += MD5_DIGEST_SIZE; ++ } ++ ++ ret = rp2040_gbdg_load_block_remote( ++ priv_data, priv_data->manifest_prep, ++ digest_write_pos - priv_data->manifest_prep, digest, true); ++ if (ret) ++ return ret; ++ ++ dev_info(&client->dev, "%s() issue CMD_SEND_MANI\n", __func__); ++ ret = rp2040_gbdg_18byte_cmd(client, CMD_SEND_MANI, digest); ++ if (ret) ++ return ret; ++ ++ ret = rp2040_gbdg_wait_until_free(client, &status); ++ if (ret) ++ return ret; ++ ++ dev_info(&client->dev, "%s() SEND_MANI response: %02x\n", __func__, ++ status); ++ ++ return status; ++} ++ ++/* Precondition: correctly initialised fast_xfer_*, gpio_base, rio_base */ ++static int rp2040_gbdg_fast_xfer(struct rp2040_gbdg *priv_data, const u8 *data, ++ size_t len) ++{ ++ struct i2c_client *client = priv_data->client; ++ void __iomem *clock_toggle; ++ void __iomem *data_set; ++ size_t clock_bank; ++ size_t data_bank; ++ u8 clock_offset; ++ u8 data_offset; ++ u32 clock_mux; ++ u32 data_mux; ++ ++ if (priv_data->fast_xfer_requires_i2c_lock) ++ i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER); ++ ++ rp2040_gbdg_rp1_read_mux(priv_data, priv_data->fast_xfer_data_index, ++ &data_mux); ++ rp2040_gbdg_rp1_read_mux(priv_data, priv_data->fast_xfer_clock_index, ++ &clock_mux); ++ ++ gpiod_direction_output(priv_data->fast_xfer_gpios->desc[0], 1); ++ gpiod_direction_output(priv_data->fast_xfer_gpios->desc[1], 0); ++ ++ rp2040_gbdg_rp1_calc_offsets(priv_data->fast_xfer_data_index, ++ &data_bank, &data_offset); ++ rp2040_gbdg_rp1_calc_offsets(priv_data->fast_xfer_clock_index, ++ &clock_bank, &clock_offset); ++ ++ data_set = priv_data->rio_base + data_bank + 0x2000; /* SET offset */ ++ clock_toggle = ++ priv_data->rio_base + clock_bank + 0x1000; /* XOR offset */ ++ ++ while (len--) { ++ /* MSB first ordering */ ++ u32 d = ~(*data++) << 4U; ++ /* ++ * Clock out each bit of data, LSB first ++ * (DDR, achieves approx 5 Mbps) ++ */ ++ for (size_t i = 0; i < 8; i++) { ++ /* Branchless set/clr data */ ++ writel(1 << data_offset, ++ data_set + ((d <<= 1) & 0x1000) /* CLR offset */ ++ ); ++ ++ /* Toggle the clock */ ++ writel(1 << clock_offset, clock_toggle); ++ } ++ } ++ ++ rp2040_gbdg_rp1_write_mux(priv_data, priv_data->fast_xfer_data_index, ++ data_mux); ++ rp2040_gbdg_rp1_write_mux(priv_data, priv_data->fast_xfer_clock_index, ++ clock_mux); ++ ++ if (priv_data->fast_xfer_requires_i2c_lock) ++ i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER); ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_transfer_bypass(struct rp2040_gbdg *priv_data, ++ const u8 *data, unsigned int length) ++{ ++ int ret; ++ u8 *buf; ++ ++ if (priv_data->fast_xfer_gpios) { ++ ret = rp2040_gbdg_10byte_cmd( ++ priv_data->client, CMD_DAT_EMIT, ++ priv_data->fast_xfer_recv_gpio_base, length); ++ return ret ? ret : ++ rp2040_gbdg_fast_xfer(priv_data, data, length); ++ } ++ ++ buf = priv_data->buffer; ++ ++ while (length) { ++ unsigned int xfer = min(length, HALF_BUFFER); ++ ++ buf[0] = DIRECT_PREFIX; ++ buf[1] = DIRECT_CMD_EMIT; ++ memcpy(&buf[2], data, xfer); ++ ret = rp2040_gbdg_i2c_send(priv_data->client, buf, xfer + 2); ++ if (ret) ++ return ret; ++ length -= xfer; ++ data += xfer; ++ } ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_transfer_cached(struct rp2040_gbdg *priv_data, ++ const u8 *data, unsigned int length) ++{ ++ int ret; ++ ++ /* ++ * Caching mechanism divides data into '8KiB - 9' (8183 byte) ++ * 'RP2040_GBDG_BLOCK_SIZE' blocks. ++ * ++ * If there's a large amount of data to send, instead, attempt to make use ++ * of a manifest. ++ */ ++ if (length > (2 * RP2040_GBDG_BLOCK_SIZE)) { ++ if (!rp2040_gbdg_transfer_manifest(priv_data, data, length)) ++ return 0; ++ } ++ ++ while (length) { ++ unsigned int xfer = min(length, RP2040_GBDG_BLOCK_SIZE); ++ ++ ret = rp2040_gbdg_transfer_block(priv_data, data, xfer); ++ if (ret) ++ return ret; ++ length -= xfer; ++ data += xfer; ++ } ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_transfer_one(struct spi_controller *ctlr, ++ struct spi_device *spi, ++ struct spi_transfer *transfer) ++{ ++ /* All transfers are performed in a synchronous manner. As such, return '0' ++ * on success or -ve on failure. (Returning +ve indicates async xfer) ++ */ ++ ++ struct rp2040_gbdg *priv_data = spi_controller_get_devdata(ctlr); ++ ++ if (priv_data->bypass_cache) { ++ return rp2040_gbdg_transfer_bypass(priv_data, transfer->tx_buf, ++ transfer->len); ++ } else { ++ return rp2040_gbdg_transfer_cached(priv_data, transfer->tx_buf, ++ transfer->len); ++ } ++} ++ ++static void rp2040_gbdg_set_cs(struct spi_device *spi, bool enable) ++{ ++ static const char disable_cs[] = { DIRECT_PREFIX, DIRECT_CMD_CS, 0x00 }; ++ static const char enable_cs[] = { DIRECT_PREFIX, DIRECT_CMD_CS, 0x10 }; ++ struct rp2040_gbdg *p_data; ++ ++ p_data = spi_controller_get_devdata(spi->controller); ++ ++ /* ++ * 'enable' is inverted and instead describes the logic level of an ++ * active-low CS. ++ */ ++ rp2040_gbdg_i2c_send(p_data->client, enable ? disable_cs : enable_cs, ++ 3); ++} ++ ++static int rp2040_gbdg_gpio_request(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct rp2040_gbdg *priv_data = gpiochip_get_data(gc); ++ u32 pattern; ++ int ret; ++ ++ if (offset >= NUM_GPIO) ++ return -EINVAL; ++ ++ pattern = (1 << (offset + 8)); ++ if (pattern & priv_data->gpio_requested) ++ return -EBUSY; ++ ++ /* Resume if previously no gpio requested */ ++ if (!priv_data->gpio_requested) { ++ ret = pm_runtime_resume_and_get(&priv_data->client->dev); ++ if (ret) { ++ dev_err(&priv_data->client->dev, ++ "%s(%u) unable to resume\n", __func__, offset); ++ return ret; ++ } ++ } ++ ++ priv_data->gpio_requested |= pattern; ++ ++ return 0; ++} ++ ++static void rp2040_gbdg_gpio_free(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct rp2040_gbdg *priv_data = gpiochip_get_data(gc); ++ u32 pattern; ++ int ret; ++ ++ if (offset >= NUM_GPIO || !priv_data->gpio_requested) ++ return; ++ ++ pattern = (1 << (offset + 8)); ++ ++ priv_data->gpio_requested &= ~pattern; ++ rp2040_gbdg_gpio_dir_in(gc, offset); ++ rp2040_gbdg_gpio_set(gc, offset, 0); ++ ++ if (!priv_data->gpio_requested) { ++ ret = pm_runtime_put_autosuspend(&priv_data->client->dev); ++ if (ret) { ++ dev_err(&priv_data->client->dev, ++ "%s(%u) unable to put_autosuspend\n", __func__, ++ offset); ++ } ++ } ++} ++ ++static int rp2040_gbdg_gpio_get_direction(struct gpio_chip *gc, ++ unsigned int offset) ++{ ++ struct rp2040_gbdg *priv_data = gpiochip_get_data(gc); ++ ++ if (offset >= NUM_GPIO) ++ return -EINVAL; ++ ++ return (priv_data->gpio_direction & (1 << (offset + 8))) ? ++ GPIO_LINE_DIRECTION_IN : ++ GPIO_LINE_DIRECTION_OUT; ++} ++ ++static int rp2040_gbdg_gpio_dir_in(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct rp2040_gbdg *priv_data = gpiochip_get_data(gc); ++ struct i2c_client *client = priv_data->client; ++ ++ if (offset >= NUM_GPIO) ++ return -EINVAL; ++ ++ priv_data->gpio_direction |= (1 << (offset + 8)); ++ ++ return rp2040_gbdg_10byte_cmd(client, CMD_GPIO_OE, ++ ~priv_data->gpio_direction, ++ priv_data->gpio_direction); ++} ++ ++static int rp2040_gbdg_gpio_dir_out(struct gpio_chip *gc, unsigned int offset, ++ int value) ++{ ++ struct rp2040_gbdg *priv_data = gpiochip_get_data(gc); ++ struct i2c_client *client = priv_data->client; ++ u32 pattern; ++ int ret; ++ ++ if (offset >= NUM_GPIO) ++ return -EINVAL; ++ ++ pattern = (1 << (offset + 8)); ++ ++ ret = rp2040_gbdg_10byte_cmd(client, CMD_GPIO_ST_CL, ++ value ? pattern : 0, !value ? pattern : 0); ++ if (ret) { ++ dev_err(&client->dev, "%s(%u, %d) could not ST_CL\n", __func__, ++ offset, value); ++ return ret; ++ } ++ ++ priv_data->gpio_direction &= ~pattern; ++ ret = rp2040_gbdg_10byte_cmd(client, CMD_GPIO_OE, ++ ~priv_data->gpio_direction, ++ priv_data->gpio_direction); ++ ++ return ret; ++} ++ ++static int rp2040_gbdg_gpio_get(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct rp2040_gbdg *priv_data = gpiochip_get_data(gc); ++ struct i2c_client *client = priv_data->client; ++ struct rp2040_gbdg_device_info info; ++ int ret; ++ ++ if (offset >= NUM_GPIO) ++ return -EINVAL; ++ ++ ret = rp2040_gbdg_get_device_info(client, &info); ++ if (ret) ++ return ret; ++ ++ return info.status & (1 << (offset + 8)) ? 1 : 0; ++} ++ ++static void rp2040_gbdg_gpio_set(struct gpio_chip *gc, unsigned int offset, ++ int value) ++{ ++ struct rp2040_gbdg *priv_data = gpiochip_get_data(gc); ++ struct i2c_client *client = priv_data->client; ++ u32 pattern; ++ ++ if (offset >= NUM_GPIO) ++ return; ++ ++ pattern = (1 << (offset + 8)); ++ rp2040_gbdg_10byte_cmd(client, CMD_GPIO_ST_CL, value ? pattern : 0, ++ !value ? pattern : 0); ++} ++ ++static int rp2040_gbdg_get_regulator(struct device *dev, ++ struct rp2040_gbdg *rp2040_gbdg) ++{ ++ struct regulator *reg = devm_regulator_get(dev, "power"); ++ ++ if (IS_ERR(reg)) ++ return PTR_ERR(reg); ++ ++ rp2040_gbdg->regulator = reg; ++ ++ return 0; ++} ++ ++static void rp2040_gbdg_parse_dt(struct rp2040_gbdg *rp2040_gbdg) ++{ ++ struct i2c_client *client = rp2040_gbdg->client; ++ struct of_phandle_args of_args[2] = { 0 }; ++ struct device *dev = &client->dev; ++ struct device_node *dn; ++ ++ rp2040_gbdg->bypass_cache = ++ of_property_read_bool(client->dev.of_node, "bypass-cache"); ++ ++ /* Optionally configure fast_xfer if RP1 is being used */ ++ if (of_parse_phandle_with_args(client->dev.of_node, "fast_xfer-gpios", ++ "#gpio-cells", 0, &of_args[0]) || ++ of_parse_phandle_with_args(client->dev.of_node, "fast_xfer-gpios", ++ "#gpio-cells", 1, &of_args[1])) { ++ dev_info(dev, "Could not parse fast_xfer-gpios phandles\n"); ++ goto node_put; ++ } ++ ++ if (of_args[0].np != of_args[1].np) { ++ dev_info( ++ dev, ++ "fast_xfer-gpios are not provided by the same controller\n"); ++ goto node_put; ++ } ++ dn = of_args[0].np; ++ if (!of_device_is_compatible(dn, "raspberrypi,rp1-gpio")) { ++ dev_info(dev, "fast_xfer-gpios controller is not an rp1\n"); ++ goto node_put; ++ } ++ if (of_args[0].args_count != 2 || of_args[1].args_count != 2) { ++ dev_info(dev, "of_args count is %d\n", of_args[0].args_count); ++ goto node_put; ++ } ++ ++ if (of_property_read_u32_index( ++ client->dev.of_node, "fast_xfer_recv_gpio_base", 0, ++ &rp2040_gbdg->fast_xfer_recv_gpio_base)) { ++ dev_info(dev, "Could not read fast_xfer_recv_gpio_base\n"); ++ goto node_put; ++ } ++ ++ rp2040_gbdg->fast_xfer_gpios = ++ devm_gpiod_get_array_optional(dev, "fast_xfer", GPIOD_ASIS); ++ if (!rp2040_gbdg->fast_xfer_gpios) { ++ dev_info(dev, "Could not acquire fast_xfer-gpios\n"); ++ goto node_put; ++ } ++ ++ rp2040_gbdg->fast_xfer_data_index = of_args[0].args[0]; ++ rp2040_gbdg->fast_xfer_clock_index = of_args[1].args[0]; ++ rp2040_gbdg->fast_xfer_requires_i2c_lock = of_property_read_bool( ++ client->dev.of_node, "fast_xfer_requires_i2c_lock"); ++ ++ rp2040_gbdg->gpio_base = of_iomap(dn, 0); ++ if (IS_ERR_OR_NULL(rp2040_gbdg->gpio_base)) { ++ dev_info(&client->dev, "%s() unable to map gpio_base\n", ++ __func__); ++ rp2040_gbdg->gpio_base = NULL; ++ devm_gpiod_put_array(dev, rp2040_gbdg->fast_xfer_gpios); ++ rp2040_gbdg->fast_xfer_gpios = NULL; ++ goto node_put; ++ } ++ ++ rp2040_gbdg->rio_base = of_iomap(dn, 1); ++ if (IS_ERR_OR_NULL(rp2040_gbdg->rio_base)) { ++ dev_info(&client->dev, "%s() unable to map rio_base\n", ++ __func__); ++ rp2040_gbdg->rio_base = NULL; ++ iounmap(rp2040_gbdg->gpio_base); ++ rp2040_gbdg->gpio_base = NULL; ++ devm_gpiod_put_array(dev, rp2040_gbdg->fast_xfer_gpios); ++ rp2040_gbdg->fast_xfer_gpios = NULL; ++ goto node_put; ++ } ++ ++node_put: ++ if (of_args[0].np) ++ of_node_put(of_args[0].np); ++ if (of_args[1].np) ++ of_node_put(of_args[1].np); ++} ++ ++static int rp2040_gbdg_power_off(struct rp2040_gbdg *rp2040_gbdg) ++{ ++ struct device *dev = &rp2040_gbdg->client->dev; ++ int ret; ++ ++ ret = regulator_disable(rp2040_gbdg->regulator); ++ if (ret) { ++ dev_err(dev, "%s: Could not disable regulator\n", __func__); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_power_on(struct rp2040_gbdg *rp2040_gbdg) ++{ ++ struct device *dev = &rp2040_gbdg->client->dev; ++ int ret; ++ ++ ret = regulator_enable(rp2040_gbdg->regulator); ++ if (ret) { ++ dev_err(dev, "%s: Could not enable regulator\n", __func__); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rp2040_gbdg_probe(struct i2c_client *client) ++{ ++ struct rp2040_gbdg_device_info info; ++ struct spi_controller *controller; ++ struct device *dev = &client->dev; ++ struct rp2040_gbdg *rp2040_gbdg; ++ struct device_node *np; ++ int ret; ++ ++ np = dev->of_node; ++ ++ controller = devm_spi_alloc_master(dev, sizeof(struct rp2040_gbdg)); ++ if (!controller) ++ return dev_err_probe(dev, ENOMEM, ++ "could not alloc spi controller\n"); ++ ++ rp2040_gbdg = spi_controller_get_devdata(controller); ++ i2c_set_clientdata(client, rp2040_gbdg); ++ rp2040_gbdg->controller = controller; ++ rp2040_gbdg->client = client; ++ ++ ret = rp2040_gbdg_get_regulator(dev, rp2040_gbdg); ++ if (ret < 0) ++ return dev_err_probe(dev, ret, "Cannot get regulator\n"); ++ ++ ret = rp2040_gbdg_power_on(rp2040_gbdg); ++ if (ret) ++ return dev_err_probe(dev, ret, "Could not power on device\n"); ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_get_noresume(dev); ++ pm_runtime_enable(dev); ++ pm_runtime_set_autosuspend_delay(dev, 1000); ++ pm_runtime_use_autosuspend(dev); ++ ++ ret = rp2040_gbdg_get_device_info(client, &info); ++ if (ret) { ++ dev_err(dev, "Could not get device info\n"); ++ goto err_pm; ++ } ++ ++ dev_info(dev, "%s() found dev ID: %llx, fw ver. %u\n", __func__, ++ info.id, info.version); ++ ++ rp2040_gbdg->shash = crypto_alloc_shash("md5", 0, 0); ++ if (IS_ERR(rp2040_gbdg->shash)) { ++ ret = PTR_ERR(rp2040_gbdg->shash); ++ dev_err(dev, "Could not allocate shash\n"); ++ goto err_pm; ++ } ++ ++ if (crypto_shash_digestsize(rp2040_gbdg->shash) != MD5_DIGEST_SIZE) { ++ ret = -EINVAL; ++ dev_err(dev, "error: Unexpected hash digest size\n"); ++ goto err_shash; ++ } ++ ++ rp2040_gbdg->shash_desc = ++ devm_kmalloc(dev, ++ sizeof(struct shash_desc) + ++ crypto_shash_descsize(rp2040_gbdg->shash), ++ 0); ++ ++ if (!rp2040_gbdg->shash_desc) { ++ ret = -ENOMEM; ++ dev_err(dev, ++ "error: Could not allocate memory for shash_desc\n"); ++ goto err_shash; ++ } ++ rp2040_gbdg->shash_desc->tfm = rp2040_gbdg->shash; ++ ++ controller->bus_num = -1; ++ controller->num_chipselect = 1; ++ controller->mode_bits = SPI_CPOL | SPI_CPHA; ++ controller->bits_per_word_mask = SPI_BPW_MASK(8); ++ controller->min_speed_hz = 35000000; ++ controller->max_speed_hz = 35000000; ++ controller->max_transfer_size = rp2040_gbdg_max_transfer_size; ++ controller->max_message_size = rp2040_gbdg_max_transfer_size; ++ controller->transfer_one = rp2040_gbdg_transfer_one; ++ controller->set_cs = rp2040_gbdg_set_cs; ++ ++ controller->dev.of_node = np; ++ controller->auto_runtime_pm = true; ++ ++ ret = devm_spi_register_controller(dev, controller); ++ if (ret) { ++ dev_err(dev, "error: Could not register SPI controller\n"); ++ goto err_shash; ++ } ++ ++ memset(&rp2040_gbdg->gc, 0, sizeof(struct gpio_chip)); ++ rp2040_gbdg->gc.parent = dev; ++ rp2040_gbdg->gc.label = MODULE_NAME; ++ rp2040_gbdg->gc.owner = THIS_MODULE; ++ rp2040_gbdg->gc.base = -1; ++ rp2040_gbdg->gc.ngpio = NUM_GPIO; ++ ++ rp2040_gbdg->gc.request = rp2040_gbdg_gpio_request; ++ rp2040_gbdg->gc.free = rp2040_gbdg_gpio_free; ++ rp2040_gbdg->gc.get_direction = rp2040_gbdg_gpio_get_direction; ++ rp2040_gbdg->gc.direction_input = rp2040_gbdg_gpio_dir_in; ++ rp2040_gbdg->gc.direction_output = rp2040_gbdg_gpio_dir_out; ++ rp2040_gbdg->gc.get = rp2040_gbdg_gpio_get; ++ rp2040_gbdg->gc.set = rp2040_gbdg_gpio_set; ++ rp2040_gbdg->gc.can_sleep = true; ++ ++ rp2040_gbdg->gpio_requested = 0; ++ ++ /* Coming out of reset, all GPIOs are inputs */ ++ rp2040_gbdg->gpio_direction = ~0; ++ ++ ret = devm_gpiochip_add_data(dev, &rp2040_gbdg->gc, rp2040_gbdg); ++ if (ret) { ++ dev_err(dev, "error: Could not add data to gpiochip\n"); ++ goto err_shash; ++ } ++ ++ rp2040_gbdg_parse_dt(rp2040_gbdg); ++ ++ pm_runtime_mark_last_busy(dev); ++ pm_runtime_put_autosuspend(dev); ++ ++ return 0; ++ ++err_shash: ++ crypto_free_shash(rp2040_gbdg->shash); ++err_pm: ++ pm_runtime_disable(dev); ++ pm_runtime_put_noidle(dev); ++ rp2040_gbdg_power_off(rp2040_gbdg); ++ ++ return ret; ++} ++ ++static void rp2040_gbdg_remove(struct i2c_client *client) ++{ ++ struct rp2040_gbdg *priv_data = i2c_get_clientdata(client); ++ ++ crypto_free_shash(priv_data->shash); ++ ++ if (priv_data->gpio_base) { ++ iounmap(priv_data->gpio_base); ++ priv_data->gpio_base = NULL; ++ } ++ if (priv_data->rio_base) { ++ iounmap(priv_data->rio_base); ++ priv_data->rio_base = NULL; ++ } ++ ++ pm_runtime_disable(&client->dev); ++ if (!pm_runtime_status_suspended(&client->dev)) ++ rp2040_gbdg_power_off(priv_data); ++ pm_runtime_set_suspended(&client->dev); ++} ++ ++static const struct i2c_device_id rp2040_gbdg_id[] = { ++ { "rp2040-gpio-bridge", 0 }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(i2c, rp2040_gbdg_id); ++ ++static const struct of_device_id rp2040_gbdg_of_match[] = { ++ { .compatible = "raspberrypi,rp2040-gpio-bridge" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rp2040_gbdg_of_match); ++ ++static int rp2040_gbdg_runtime_suspend(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ return rp2040_gbdg_power_off(i2c_get_clientdata(client)); ++} ++ ++static int rp2040_gbdg_runtime_resume(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ return rp2040_gbdg_power_on(i2c_get_clientdata(client)); ++} ++ ++static const struct dev_pm_ops rp2040_gbdg_pm_ops = { SET_RUNTIME_PM_OPS( ++ rp2040_gbdg_runtime_suspend, rp2040_gbdg_runtime_resume, NULL) }; ++ ++static struct i2c_driver rp2040_gbdg_driver = { ++ .driver = { ++ .name = MODULE_NAME, ++ .of_match_table = of_match_ptr(rp2040_gbdg_of_match), ++ .pm = &rp2040_gbdg_pm_ops, ++ }, ++ .probe = rp2040_gbdg_probe, ++ .remove = rp2040_gbdg_remove, ++ .id_table = rp2040_gbdg_id, ++}; ++ ++module_i2c_driver(rp2040_gbdg_driver); ++ ++MODULE_AUTHOR("Richard Oliver "); ++MODULE_DESCRIPTION("Raspberry Pi RP2040 GPIO Bridge"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/bcm27xx/patches-6.6/950-1166-dmaengine-dw-axi-dmac-Honour-snps-block-size.patch b/target/linux/bcm27xx/patches-6.6/950-1166-dmaengine-dw-axi-dmac-Honour-snps-block-size.patch new file mode 100644 index 0000000000..85b1cf6448 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1166-dmaengine-dw-axi-dmac-Honour-snps-block-size.patch @@ -0,0 +1,52 @@ +From 475cddaba6b02584157e1c128a5a6858770a3d06 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 10 Jul 2024 14:47:17 +0100 +Subject: [PATCH 1166/1215] dmaengine: dw-axi-dmac: Honour snps,block-size + +The snps,block-size DT property declares the maximum block size for each +channel of the dw-axi-dmac. However, the driver ignores these when +setting max_seg_size and uses MAX_BLOCK_SIZE (4096) instead. + +To take advantage of the efficiencies of larger blocks, calculate the +minimum block size across all channels and use that instead. + +See: https://github.com/raspberrypi/linux/issues/6256 + +Signed-off-by: Phil Elwell +--- + drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -1470,6 +1470,7 @@ static int dw_probe(struct platform_devi + struct dw_axi_dma *dw; + struct dw_axi_dma_hcfg *hdata; + struct reset_control *resets; ++ unsigned int max_seg_size; + unsigned int flags; + u32 i; + int ret; +@@ -1585,9 +1586,21 @@ static int dw_probe(struct platform_devi + * Synopsis DesignWare AxiDMA datasheet mentioned Maximum + * supported blocks is 1024. Device register width is 4 bytes. + * Therefore, set constraint to 1024 * 4. ++ * However, if all channels specify a greater value, use that instead. + */ ++ + dw->dma.dev->dma_parms = &dw->dma_parms; +- dma_set_max_seg_size(&pdev->dev, MAX_BLOCK_SIZE); ++ max_seg_size = UINT_MAX; ++ for (i = 0; i < dw->hdata->nr_channels; i++) { ++ unsigned int block_size = chip->dw->hdata->block_size[i]; ++ ++ if (!block_size) ++ block_size = MAX_BLOCK_SIZE; ++ max_seg_size = min(block_size, max_seg_size); ++ } ++ ++ dma_set_max_seg_size(&pdev->dev, max_seg_size); ++ + platform_set_drvdata(pdev, chip); + + pm_runtime_enable(chip->dev); diff --git a/target/linux/bcm27xx/patches-6.6/950-1167-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch b/target/linux/bcm27xx/patches-6.6/950-1167-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch new file mode 100644 index 0000000000..2ba494958e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1167-mmc-restrict-posted-write-counts-for-SD-cards-in-CQ-.patch @@ -0,0 +1,157 @@ +From e6c1e862b2b8150a419f4208e5bd7749662b16a1 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Thu, 20 Jun 2024 14:31:20 +0100 +Subject: [PATCH 1167/1215] mmc: restrict posted write counts for SD cards in + CQ mode + +Command Queueing requires Write Cache and Power off Notification support +from the card - but using the write cache forms a contract with the host +whereby the card expects to be told about impending power-down. + +The implication is that (for performance) the card can do unsafe things +with pending write data - including reordering what gets committed to +nonvolatile storage at what time. + +Exposed SD slots and platforms powered by hotpluggable means (i.e. +Raspberry Pis) can't guarantee that surprise removal won't happen. + +To limit the scope for cards to invent new ways to trash filesystems, +limit pending writes to 1 (equivalent to the non-CQ behaviour). + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/core/block.c | 11 +++++++++-- + drivers/mmc/core/mmc.c | 1 + + drivers/mmc/core/queue.c | 9 +++++++++ + drivers/mmc/core/queue.h | 1 + + drivers/mmc/core/sd.c | 8 ++++++++ + include/linux/mmc/card.h | 2 ++ + 6 files changed, 30 insertions(+), 2 deletions(-) + +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -1555,6 +1555,8 @@ static void mmc_blk_cqe_complete_rq(stru + + spin_lock_irqsave(&mq->lock, flags); + ++ if (req_op(req) == REQ_OP_WRITE) ++ mq->pending_writes--; + mq->in_flight[issue_type] -= 1; + + put_card = (mmc_tot_in_flight(mq) == 0); +@@ -2071,6 +2073,8 @@ static void mmc_blk_mq_complete_rq(struc + struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); + unsigned int nr_bytes = mqrq->brq.data.bytes_xfered; + ++ if (req_op(req) == REQ_OP_WRITE) ++ mq->pending_writes--; + if (nr_bytes) { + if (blk_update_request(req, BLK_STS_OK, nr_bytes)) + blk_mq_requeue_request(req, true); +@@ -2165,13 +2169,16 @@ static void mmc_blk_mq_poll_completion(s + mmc_blk_urgent_bkops(mq, mqrq); + } + +-static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type) ++static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type, ++ struct request *req) + { + unsigned long flags; + bool put_card; + + spin_lock_irqsave(&mq->lock, flags); + ++ if (req_op(req) == REQ_OP_WRITE) ++ mq->pending_writes--; + mq->in_flight[issue_type] -= 1; + + put_card = (mmc_tot_in_flight(mq) == 0); +@@ -2205,7 +2212,7 @@ static void mmc_blk_mq_post_req(struct m + blk_mq_complete_request(req); + } + +- mmc_blk_mq_dec_in_flight(mq, issue_type); ++ mmc_blk_mq_dec_in_flight(mq, issue_type, req); + } + + void mmc_blk_mq_recovery(struct mmc_queue *mq) +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1922,6 +1922,7 @@ static int mmc_init_card(struct mmc_host + pr_info("%s: Host Software Queue enabled\n", + mmc_hostname(host)); + } ++ card->max_posted_writes = card->ext_csd.cmdq_depth; + } + } + +--- a/drivers/mmc/core/queue.c ++++ b/drivers/mmc/core/queue.c +@@ -268,6 +268,11 @@ static blk_status_t mmc_mq_queue_rq(stru + spin_unlock_irq(&mq->lock); + return BLK_STS_RESOURCE; + } ++ if (host->cqe_enabled && req_op(req) == REQ_OP_WRITE && ++ mq->pending_writes >= card->max_posted_writes) { ++ spin_unlock_irq(&mq->lock); ++ return BLK_STS_RESOURCE; ++ } + break; + default: + /* +@@ -284,6 +289,8 @@ static blk_status_t mmc_mq_queue_rq(stru + /* Parallel dispatch of requests is not supported at the moment */ + mq->busy = true; + ++ if (req_op(req) == REQ_OP_WRITE) ++ mq->pending_writes++; + mq->in_flight[issue_type] += 1; + get_card = (mmc_tot_in_flight(mq) == 1); + cqe_retune_ok = (mmc_cqe_qcnt(mq) == 1); +@@ -323,6 +330,8 @@ static blk_status_t mmc_mq_queue_rq(stru + bool put_card = false; + + spin_lock_irq(&mq->lock); ++ if (req_op(req) == REQ_OP_WRITE) ++ mq->pending_writes--; + mq->in_flight[issue_type] -= 1; + if (mmc_tot_in_flight(mq) == 0) + put_card = true; +--- a/drivers/mmc/core/queue.h ++++ b/drivers/mmc/core/queue.h +@@ -79,6 +79,7 @@ struct mmc_queue { + struct request_queue *queue; + spinlock_t lock; + int in_flight[MMC_ISSUE_MAX]; ++ int pending_writes; + unsigned int cqe_busy; + #define MMC_CQE_DCMD_BUSY BIT(0) + bool busy; +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -1104,6 +1104,14 @@ static int sd_parse_ext_reg_perf(struct + pr_debug("%s: Command Queue supported depth %u\n", + mmc_hostname(card->host), + card->ext_csd.cmdq_depth); ++ /* ++ * If CQ is enabled, there is a contract between host and card such that VDD will ++ * be maintained and removed only if a power off notification is provided. ++ * An SD card in an accessible slot means surprise removal is a possibility. ++ * As a middle ground, limit max posted writes to 1 unless the card is "hardwired". ++ */ ++ if (mmc_card_is_removable(card->host)) ++ card->max_posted_writes = 1; + } + + card->ext_perf.fno = fno; +--- a/include/linux/mmc/card.h ++++ b/include/linux/mmc/card.h +@@ -343,6 +343,8 @@ struct mmc_card { + unsigned int nr_parts; + + struct workqueue_struct *complete_wq; /* Private workqueue */ ++ ++ unsigned int max_posted_writes; /* command queue posted write limit */ + }; + + static inline bool mmc_large_sector(struct mmc_card *card) diff --git a/target/linux/bcm27xx/patches-6.6/950-1168-fixup-mmc-restrict-posted-write-counts-for-SD-cards-.patch b/target/linux/bcm27xx/patches-6.6/950-1168-fixup-mmc-restrict-posted-write-counts-for-SD-cards-.patch new file mode 100644 index 0000000000..4f1d02c74d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1168-fixup-mmc-restrict-posted-write-counts-for-SD-cards-.patch @@ -0,0 +1,70 @@ +From 19682239a60c1b53cad8319eaeb58e71d4213cee Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 15 Jul 2024 13:38:38 +0100 +Subject: [PATCH 1168/1215] fixup: mmc: restrict posted write counts for SD + cards in CQ mode + +Leaving card->max_posted_writes unintialised was a bad thing to do. + +Also, cqe_enable is 1 if hsq is enabled as hsq substitutes the cqhci +implementation with its own. + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/core/mmc.c | 1 + + drivers/mmc/core/queue.c | 2 +- + drivers/mmc/core/sd.c | 14 ++++++++------ + 3 files changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/mmc/core/mmc.c ++++ b/drivers/mmc/core/mmc.c +@@ -1663,6 +1663,7 @@ static int mmc_init_card(struct mmc_host + card->ocr = ocr; + card->type = MMC_TYPE_MMC; + card->rca = 1; ++ card->max_posted_writes = 1; + memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); + } + +--- a/drivers/mmc/core/queue.c ++++ b/drivers/mmc/core/queue.c +@@ -268,7 +268,7 @@ static blk_status_t mmc_mq_queue_rq(stru + spin_unlock_irq(&mq->lock); + return BLK_STS_RESOURCE; + } +- if (host->cqe_enabled && req_op(req) == REQ_OP_WRITE && ++ if (!host->hsq_enabled && host->cqe_enabled && req_op(req) == REQ_OP_WRITE && + mq->pending_writes >= card->max_posted_writes) { + spin_unlock_irq(&mq->lock); + return BLK_STS_RESOURCE; +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -1105,13 +1105,14 @@ static int sd_parse_ext_reg_perf(struct + mmc_hostname(card->host), + card->ext_csd.cmdq_depth); + /* +- * If CQ is enabled, there is a contract between host and card such that VDD will +- * be maintained and removed only if a power off notification is provided. +- * An SD card in an accessible slot means surprise removal is a possibility. +- * As a middle ground, limit max posted writes to 1 unless the card is "hardwired". ++ * If CQ is enabled, there is a contract between host and card such that ++ * VDD will be maintained and removed only if a power off notification ++ * is provided. An SD card in an accessible slot means surprise removal ++ * is a possibility. As a middle ground, keep the default maximum of 1 ++ * posted write unless the card is "hardwired". + */ +- if (mmc_card_is_removable(card->host)) +- card->max_posted_writes = 1; ++ if (!mmc_card_is_removable(card->host)) ++ card->max_posted_writes = card->ext_csd.cmdq_depth; + } + + card->ext_perf.fno = fno; +@@ -1383,6 +1384,7 @@ retry: + + card->ocr = ocr; + card->type = MMC_TYPE_SD; ++ card->max_posted_writes = 1; + memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); + } + diff --git a/target/linux/bcm27xx/patches-6.6/950-1169-mmc-brcmstb-don-t-squash-card-busy-detection-on-bcm2.patch b/target/linux/bcm27xx/patches-6.6/950-1169-mmc-brcmstb-don-t-squash-card-busy-detection-on-bcm2.patch new file mode 100644 index 0000000000..0d4d6cba19 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1169-mmc-brcmstb-don-t-squash-card-busy-detection-on-bcm2.patch @@ -0,0 +1,28 @@ +From 1abc413af44652d6a76d5b5c2afe90788595008e Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 15 Jul 2024 13:57:01 +0100 +Subject: [PATCH 1169/1215] mmc: brcmstb: don't squash card-busy detection on + bcm2712 + +Commit 485d9421719b ("mmc: sdhci-brcmstb: check R1_STATUS for +erase/trim/discard") introduced a new flag and defaulted to disabling +card busy detection across all platforms with this controller. + +This is required for IO voltage switching, as the card drives CMD low +while the switch is in progress. + +Signed-off-by: Jonathan Bell +--- + drivers/mmc/host/sdhci-brcmstb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mmc/host/sdhci-brcmstb.c ++++ b/drivers/mmc/host/sdhci-brcmstb.c +@@ -430,6 +430,7 @@ static const struct brcmstb_match_priv m + }; + + static const struct brcmstb_match_priv match_priv_2712 = { ++ .flags = BRCMSTB_MATCH_FLAGS_USE_CARD_BUSY, + .hs400es = sdhci_brcmstb_hs400es, + .cfginit = sdhci_brcmstb_cfginit_2712, + .ops = &sdhci_brcmstb_ops_2712, diff --git a/target/linux/bcm27xx/patches-6.6/950-1172-Revert-Update-DAC8x-to-support-384khz-6187.patch b/target/linux/bcm27xx/patches-6.6/950-1172-Revert-Update-DAC8x-to-support-384khz-6187.patch new file mode 100644 index 0000000000..1923b7aec0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1172-Revert-Update-DAC8x-to-support-384khz-6187.patch @@ -0,0 +1,25 @@ +From 31eb43be8cad2818b4458cf1fd2dfa60031ee5f4 Mon Sep 17 00:00:00 2001 +From: Matthew +Date: Tue, 16 Jul 2024 11:20:54 +0200 +Subject: [PATCH 1172/1215] Revert "Update DAC8x to support 384khz (#6187)" + +This reverts commit dd7a15472b18d4bce738bb9213443c140473833b. +--- + sound/soc/bcm/rpi-simple-soundcard.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/bcm/rpi-simple-soundcard.c ++++ b/sound/soc/bcm/rpi-simple-soundcard.c +@@ -324,10 +324,10 @@ static int hifiberry_dac8x_init(struct s + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + + /* override the defaults to reflect 4 x PCM5102A on the card +- * and limit the sample rate to 384ksps ++ * and limit the sample rate to 192ksps + */ + codec_dai->driver->playback.channels_max = 8; +- codec_dai->driver->playback.rates = SNDRV_PCM_RATE_8000_384000; ++ codec_dai->driver->playback.rates = SNDRV_PCM_RATE_8000_192000; + + return 0; + } diff --git a/target/linux/bcm27xx/patches-6.6/950-1176-dt-bindings-clk-rp1-Add-clocks-representing-MIPI-DSI.patch b/target/linux/bcm27xx/patches-6.6/950-1176-dt-bindings-clk-rp1-Add-clocks-representing-MIPI-DSI.patch new file mode 100644 index 0000000000..af740bd305 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1176-dt-bindings-clk-rp1-Add-clocks-representing-MIPI-DSI.patch @@ -0,0 +1,25 @@ +From 3224569a3e279bbeae4e975dfa1a890f3f595239 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Fri, 10 May 2024 15:18:44 +0100 +Subject: [PATCH 1176/1215] dt-bindings: clk: rp1: Add clocks representing MIPI + DSI byteclock + +Define two new RP1 clocks, representing the MIPI DSI byteclock +sources for the dividers used to generate MIPI[01] DPI pixel clocks. +(Previously they were represented by "fake" fixed clocks sources). + +Signed-off-by: Nick Hollinghurst +--- + include/dt-bindings/clock/rp1.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/include/dt-bindings/clock/rp1.h ++++ b/include/dt-bindings/clock/rp1.h +@@ -54,3 +54,7 @@ + /* Extra PLL output channels - RP1B0 only */ + #define RP1_PLL_VIDEO_PRI_PH 43 + #define RP1_PLL_AUDIO_TERN 44 ++ ++/* MIPI clocks managed by the DSI driver */ ++#define RP1_CLK_MIPI0_DSI_BYTECLOCK 45 ++#define RP1_CLK_MIPI1_DSI_BYTECLOCK 46 diff --git a/target/linux/bcm27xx/patches-6.6/950-1177-clk-clk-rp1-Add-varsrc-clocks-to-represent-MIPI-byte.patch b/target/linux/bcm27xx/patches-6.6/950-1177-clk-clk-rp1-Add-varsrc-clocks-to-represent-MIPI-byte.patch new file mode 100644 index 0000000000..564ef84c9e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1177-clk-clk-rp1-Add-varsrc-clocks-to-represent-MIPI-byte.patch @@ -0,0 +1,132 @@ +From 126560c909f38f00c08dd5f35f50c981d5e25e1f Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Fri, 10 May 2024 15:30:44 +0100 +Subject: [PATCH 1177/1215] clk: clk-rp1: Add "varsrc" clocks to represent MIPI + byte clocks + +Add a new class of clocks to RP1 to represent clock sources whose +frequency changes at run-time as a side-effect of some other driver. +Specifically this is for the two MIPI DSI byte-clock sources. + +Signed-off-by: Nick Hollinghurst +--- + drivers/clk/clk-rp1.c | 73 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 73 insertions(+) + +--- a/drivers/clk/clk-rp1.c ++++ b/drivers/clk/clk-rp1.c +@@ -394,6 +394,11 @@ struct rp1_clock { + unsigned long cached_rate; + }; + ++struct rp1_varsrc { ++ struct clk_hw hw; ++ struct rp1_clockman *clockman; ++ unsigned long rate; ++}; + + struct rp1_clk_change { + struct clk_hw *hw; +@@ -1414,6 +1419,34 @@ static void rp1_clk_debug_init(struct cl + rp1_debugfs_regset(clockman, 0, regs, i, dentry); + } + ++static int rp1_varsrc_set_rate(struct clk_hw *hw, ++ unsigned long rate, unsigned long parent_rate) ++{ ++ struct rp1_varsrc *varsrc = container_of(hw, struct rp1_varsrc, hw); ++ ++ /* ++ * "varsrc" exists purely to let clock dividers know the frequency ++ * of an externally-managed clock source (such as MIPI DSI byte-clock) ++ * which may change at run-time as a side-effect of some other driver. ++ */ ++ varsrc->rate = rate; ++ return 0; ++} ++ ++static unsigned long rp1_varsrc_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct rp1_varsrc *varsrc = container_of(hw, struct rp1_varsrc, hw); ++ ++ return varsrc->rate; ++} ++ ++static long rp1_varsrc_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ return rate; ++} ++ + static const struct clk_ops rp1_pll_core_ops = { + .is_prepared = rp1_pll_core_is_on, + .prepare = rp1_pll_core_on, +@@ -1464,6 +1497,12 @@ static const struct clk_ops rp1_clk_ops + .debug_init = rp1_clk_debug_init, + }; + ++static const struct clk_ops rp1_varsrc_ops = { ++ .set_rate = rp1_varsrc_set_rate, ++ .recalc_rate = rp1_varsrc_recalc_rate, ++ .round_rate = rp1_varsrc_round_rate, ++}; ++ + static bool rp1_clk_is_claimed(const char *name); + + static struct clk_hw *rp1_register_pll_core(struct rp1_clockman *clockman, +@@ -1647,6 +1686,35 @@ static struct clk_hw *rp1_register_clock + return &clock->hw; + } + ++static struct clk_hw *rp1_register_varsrc(struct rp1_clockman *clockman, ++ const void *data) ++{ ++ const char *name = *(char const * const *)data; ++ struct rp1_varsrc *clock; ++ struct clk_init_data init; ++ int ret; ++ ++ memset(&init, 0, sizeof(init)); ++ init.parent_names = &ref_clock; ++ init.num_parents = 1; ++ init.name = name; ++ init.flags = CLK_IGNORE_UNUSED; ++ init.ops = &rp1_varsrc_ops; ++ ++ clock = devm_kzalloc(clockman->dev, sizeof(*clock), GFP_KERNEL); ++ if (!clock) ++ return NULL; ++ ++ clock->clockman = clockman; ++ clock->hw.init = &init; ++ ++ ret = devm_clk_hw_register(clockman->dev, &clock->hw); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ return &clock->hw; ++} ++ + struct rp1_clk_desc { + struct clk_hw *(*clk_register)(struct rp1_clockman *clockman, + const void *data); +@@ -1676,6 +1744,8 @@ struct rp1_clk_desc { + &(struct rp1_clock_data) \ + {__VA_ARGS__}) + ++#define REGISTER_VARSRC(n) _REGISTER(&rp1_register_varsrc, &(const char *){n}) ++ + static const struct rp1_clk_desc clk_desc_array[] = { + [RP1_PLL_SYS_CORE] = REGISTER_PLL_CORE( + .name = "pll_sys_core", +@@ -2318,6 +2388,9 @@ static const struct rp1_clk_desc clk_des + .max_freq = 200 * MHz, + .fc0_src = FC_NUM(3, 6), + ), ++ ++ [RP1_CLK_MIPI0_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi0_dsi_byteclk"), ++ [RP1_CLK_MIPI1_DSI_BYTECLOCK] = REGISTER_VARSRC("clksrc_mipi1_dsi_byteclk"), + }; + + static bool rp1_clk_claimed[ARRAY_SIZE(clk_desc_array)]; diff --git a/target/linux/bcm27xx/patches-6.6/950-1178-dts-rp1-DSI-drivers-to-use-newly-defined-MIPI-byte-s.patch b/target/linux/bcm27xx/patches-6.6/950-1178-dts-rp1-DSI-drivers-to-use-newly-defined-MIPI-byte-s.patch new file mode 100644 index 0000000000..7e6032dd1f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1178-dts-rp1-DSI-drivers-to-use-newly-defined-MIPI-byte-s.patch @@ -0,0 +1,92 @@ +From 9a108c82b6f6526e0aa8a19befa1ed3f31f8fe52 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Fri, 10 May 2024 15:42:29 +0100 +Subject: [PATCH 1178/1215] dts: rp1: DSI drivers to use newly defined MIPI + byte source clocks. + +Remove the "dummy" 72MHz fixed clock sources and associate DSI driver +with the new "variable" clock sources now defined in RP1 clocks. + +Also add PLLSYS clock to DSI, which it will need as an alternative +clock source in those cases where DPI pixclock > DSI byteclock. + +Signed-off-by: Nick Hollinghurst +--- + arch/arm/boot/dts/broadcom/rp1.dtsi | 50 +++++++++-------------------- + 1 file changed, 15 insertions(+), 35 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/rp1.dtsi ++++ b/arch/arm/boot/dts/broadcom/rp1.dtsi +@@ -1109,16 +1109,15 @@ + + interrupts = ; + +- clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, // required, config bus clock +- <&rp1_clocks RP1_CLK_MIPI0_DPI>, // required, pixel clock +- <&clksrc_mipi0_dsi_byteclk>, // internal, parent for divide +- <&clk_xosc>; // hardwired to DSI "refclk" +- clock-names = "cfgclk", "dpiclk", "byteclk", "refclk"; ++ clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, ++ <&rp1_clocks RP1_CLK_MIPI0_DPI>, ++ <&rp1_clocks RP1_CLK_MIPI0_DSI_BYTECLOCK>, ++ <&clk_xosc>, // hardwired to DSI "refclk" ++ <&rp1_clocks RP1_PLL_SYS>; // alternate parent for divide ++ clock-names = "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys"; + +- assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, +- <&rp1_clocks RP1_CLK_MIPI0_DPI>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; + assigned-clock-rates = <25000000>; +- assigned-clock-parents = <0>, <&clksrc_mipi0_dsi_byteclk>; + }; + + rp1_dsi1: dsi@128000 { +@@ -1130,16 +1129,15 @@ + + interrupts = ; + +- clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, // required, config bus clock +- <&rp1_clocks RP1_CLK_MIPI1_DPI>, // required, pixel clock +- <&clksrc_mipi1_dsi_byteclk>, // internal, parent for divide +- <&clk_xosc>; // hardwired to DSI "refclk" +- clock-names = "cfgclk", "dpiclk", "byteclk", "refclk"; ++ clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, ++ <&rp1_clocks RP1_CLK_MIPI1_DPI>, ++ <&rp1_clocks RP1_CLK_MIPI1_DSI_BYTECLOCK>, ++ <&clk_xosc>, // hardwired to DSI "refclk" ++ <&rp1_clocks RP1_PLL_SYS>; // alternate parent for divide ++ clock-names = "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys"; + +- assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, +- <&rp1_clocks RP1_CLK_MIPI1_DPI>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; + assigned-clock-rates = <25000000>; +- assigned-clock-parents = <0>, <&clksrc_mipi1_dsi_byteclk>; + }; + + /* VEC and DPI both need to control PLL_VIDEO and cannot work together; */ +@@ -1216,24 +1214,6 @@ + clock-output-names = "core"; + clock-frequency = <50000000>; + }; +- clksrc_mipi0_dsi_byteclk: clksrc_mipi0_dsi_byteclk { +- // This clock is synthesized by MIPI0 D-PHY, when DSI is running. +- // Its frequency is not known a priori (until a panel driver attaches) +- // so assign a made-up frequency of 72MHz so it can be divided for DPI. +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "clksrc_mipi0_dsi_byteclk"; +- clock-frequency = <72000000>; +- }; +- clksrc_mipi1_dsi_byteclk: clksrc_mipi1_dsi_byteclk { +- // This clock is synthesized by MIPI1 D-PHY, when DSI is running. +- // Its frequency is not known a priori (until a panel driver attaches) +- // so assign a made-up frequency of 72MHz so it can be divided for DPI. +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "clksrc_mipi1_dsi_byteclk"; +- clock-frequency = <72000000>; +- }; + /* GPIO derived clock sources. Each GPIO with a GPCLK function + * can drive its output from the respective GPCLK + * generator, and provide a clock source to other internal diff --git a/target/linux/bcm27xx/patches-6.6/950-1179-drm-rp1-rp1-dsi-Switch-to-PLL_SYS-source-for-DPI-whe.patch b/target/linux/bcm27xx/patches-6.6/950-1179-drm-rp1-rp1-dsi-Switch-to-PLL_SYS-source-for-DPI-whe.patch new file mode 100644 index 0000000000..a80af9839d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1179-drm-rp1-rp1-dsi-Switch-to-PLL_SYS-source-for-DPI-whe.patch @@ -0,0 +1,313 @@ +From f5de8d46da4b40f2180be502c1e547fe8c9b2ac2 Mon Sep 17 00:00:00 2001 +From: Nick Hollinghurst +Date: Fri, 10 May 2024 15:48:15 +0100 +Subject: [PATCH 1179/1215] drm: rp1: rp1-dsi: Switch to PLL_SYS source for DPI + when 8 * lanes > bpp + +To support 4 lanes, re-parent DPI clock source between DSI byteclock +(using the new "variable sources" defined in clk-rp1) and PLL_SYS. +This is to cover cases in which byteclock < pixclock <= 200MHz. + +Tidying: All frequencies now in Hz (not kHz), where DSI speed is now +represented by byteclock to simplify arithmetic. Clamp DPI and byte +clocks to their legal ranges; fix up HSTX timeout to avoid an unsafe +assumption that it would return to LP state for every scanline. + +Because of RP1's clock topology, the ratio between DSI and DPI clocks +may not be exact with 3 or 4 lanes, leading to slightly irregular +timings each time DSI switches between HS and LP states. Tweak to +inhibit LP during Horizontal BP when sync pulses were requested. + +Signed-off-by: Nick Hollinghurst +--- + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c | 3 +- + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h | 3 +- + drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c | 130 +++++++++++++--------- + 3 files changed, 80 insertions(+), 56 deletions(-) + +--- a/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.c +@@ -54,6 +54,7 @@ static void rp1_dsi_bridge_pre_enable(st + struct rp1_dsi *dsi = bridge_to_rp1_dsi(bridge); + + rp1dsi_dsi_setup(dsi, &dsi->pipe.crtc.state->adjusted_mode); ++ dsi->dsi_running = true; + } + + static void rp1_dsi_bridge_enable(struct drm_bridge *bridge, +@@ -443,7 +444,7 @@ static int rp1dsi_platform_probe(struct + /* Hardware resources */ + for (i = 0; i < RP1DSI_NUM_CLOCKS; i++) { + static const char * const myclocknames[RP1DSI_NUM_CLOCKS] = { +- "cfgclk", "dpiclk", "byteclk", "refclk" ++ "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys" + }; + dsi->clocks[i] = devm_clk_get(dev, myclocknames[i]); + if (IS_ERR(dsi->clocks[i])) { +--- a/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi.h +@@ -30,7 +30,8 @@ + #define RP1DSI_CLOCK_DPI 1 + #define RP1DSI_CLOCK_BYTE 2 + #define RP1DSI_CLOCK_REF 3 +-#define RP1DSI_NUM_CLOCKS 4 ++#define RP1DSI_CLOCK_PLLSYS 4 ++#define RP1DSI_NUM_CLOCKS 5 + + /* ---------------------------------------------------------------------- */ + +--- a/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c ++++ b/drivers/gpu/drm/rp1/rp1-dsi/rp1_dsi_dsi.c +@@ -7,6 +7,7 @@ + + #include + #include ++#include + #include + #include + #include "drm/drm_print.h" +@@ -1111,7 +1112,7 @@ static void dphy_transaction(struct rp1_ + DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS); + } + +-static uint8_t dphy_get_div(u32 refclk_khz, u32 vco_freq_khz, u32 *ptr_m, u32 *ptr_n) ++static u64 dphy_get_div(u32 refclk, u64 vco_freq, u32 *ptr_m, u32 *ptr_n) + { + /* + * See pg 77-78 of dphy databook +@@ -1124,19 +1125,23 @@ static uint8_t dphy_get_div(u32 refclk_k + * In practice, given a 50MHz reference clock, it can produce any + * multiple of 10MHz, 11.1111MHz, 12.5MHz, 14.286MHz or 16.667MHz + * with < 1% error for all frequencies above 495MHz. ++ * ++ * vco_freq should be set to the lane bit rate (not the MIPI clock ++ * which is half of this). These frequencies are now measured in Hz. ++ * They should fit within u32, but u64 is needed for calculations. + */ + +- static const u32 REF_DIVN_MAX = 40000u; +- static const u32 REF_DIVN_MIN = 5000u; +- u32 best_n, best_m, best_err = 0x7fffffff; +- unsigned int n; ++ static const u32 REF_DIVN_MAX = 40000000; ++ static const u32 REF_DIVN_MIN = 5000000; ++ u32 n, best_n, best_m; ++ u64 best_err = vco_freq; + +- for (n = 1 + refclk_khz / REF_DIVN_MAX; n * REF_DIVN_MIN <= refclk_khz && n < 100; ++n) { +- u32 half_m = (n * vco_freq_khz + refclk_khz) / (2 * refclk_khz); ++ for (n = 1 + refclk / REF_DIVN_MAX; n * REF_DIVN_MIN <= refclk && n < 100; ++n) { ++ u32 half_m = DIV_U64_ROUND_CLOSEST(n * vco_freq, 2 * refclk); + + if (half_m < 150) { +- u32 f = (2 * half_m * refclk_khz) / n; +- u32 err = (f > vco_freq_khz) ? f - vco_freq_khz : vco_freq_khz - f; ++ u64 f = div_u64(mul_u32_u32(2 * half_m, refclk), n); ++ u64 err = (f > vco_freq) ? f - vco_freq : vco_freq - f; + + if (err < best_err) { + best_n = n; +@@ -1148,12 +1153,12 @@ static uint8_t dphy_get_div(u32 refclk_k + } + } + +- if (64 * best_err < vco_freq_khz) { /* tolerate small error */ +- *ptr_n = best_n; +- *ptr_m = best_m; +- return 1; +- } +- return 0; ++ if (64 * best_err >= vco_freq) ++ return 0; ++ ++ *ptr_n = best_n; ++ *ptr_m = best_m; ++ return div_u64(mul_u32_u32(best_m, refclk), best_n); + } + + struct hsfreq_range { +@@ -1226,13 +1231,14 @@ static void dphy_set_hsfreqrange(struct + hsfreq_table[i].hsfreqrange << 1); + } + +-static void dphy_configure_pll(struct rp1_dsi *dsi, u32 refclk_khz, u32 vco_freq_khz) ++static u32 dphy_configure_pll(struct rp1_dsi *dsi, u32 refclk, u32 vco_freq) + { + u32 m = 0; + u32 n = 0; ++ u32 actual_vco_freq = dphy_get_div(refclk, vco_freq, &m, &n); + +- if (dphy_get_div(refclk_khz, vco_freq_khz, &m, &n)) { +- dphy_set_hsfreqrange(dsi, vco_freq_khz / 1000); ++ if (actual_vco_freq) { ++ dphy_set_hsfreqrange(dsi, actual_vco_freq / 1000000); + /* Program m,n from registers */ + dphy_transaction(dsi, DPHY_PLL_DIV_CTRL_OFFSET, 0x30); + /* N (program N-1) */ +@@ -1242,18 +1248,21 @@ static void dphy_configure_pll(struct rp + /* M[4:0] (program M-1) */ + dphy_transaction(dsi, DPHY_PLL_LOOP_DIV_OFFSET, ((m - 1) & 0x1F)); + drm_dbg_driver(dsi->drm, +- "DPHY: vco freq want %dkHz got %dkHz = %d * (%dkHz / %d), hsfreqrange = 0x%02x\r\n", +- vco_freq_khz, refclk_khz * m / n, m, refclk_khz, +- n, hsfreq_table[dsi->hsfreq_index].hsfreqrange); ++ "DPHY: vco freq want %uHz got %uHz = %d * (%uHz / %d), hsfreqrange = 0x%02x\n", ++ vco_freq, actual_vco_freq, m, refclk, n, ++ hsfreq_table[dsi->hsfreq_index].hsfreqrange); + } else { +- drm_info(dsi->drm, +- "rp1dsi: Error configuring DPHY PLL! %dkHz = %d * (%dkHz / %d)\r\n", +- vco_freq_khz, m, refclk_khz, n); ++ drm_warn(dsi->drm, ++ "rp1dsi: Error configuring DPHY PLL %uHz\n", vco_freq); + } ++ ++ return actual_vco_freq; + } + +-static void dphy_init_khz(struct rp1_dsi *dsi, u32 ref_freq, u32 vco_freq) ++static u32 dphy_init(struct rp1_dsi *dsi, u32 ref_freq, u32 vco_freq) + { ++ u32 actual_vco_freq; ++ + /* Reset the PHY */ + DSI_WRITE(DSI_PHYRSTZ, 0); + DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS); +@@ -1263,13 +1272,15 @@ static void dphy_init_khz(struct rp1_dsi + DSI_WRITE(DSI_PHY_TST_CTRL0, DPHY_CTRL0_PHY_TESTCLK_BITS); + udelay(1); + /* Since we are in DSI (not CSI2) mode here, start the PLL */ +- dphy_configure_pll(dsi, ref_freq, vco_freq); ++ actual_vco_freq = dphy_configure_pll(dsi, ref_freq, vco_freq); + udelay(1); + /* Unreset */ + DSI_WRITE(DSI_PHYRSTZ, DSI_PHYRSTZ_SHUTDOWNZ_BITS); + udelay(1); + DSI_WRITE(DSI_PHYRSTZ, (DSI_PHYRSTZ_SHUTDOWNZ_BITS | DSI_PHYRSTZ_RSTZ_BITS)); + udelay(1); /* so we can see PLL coming up? */ ++ ++ return actual_vco_freq; + } + + void rp1dsi_mipicfg_setup(struct rp1_dsi *dsi) +@@ -1290,23 +1301,30 @@ static unsigned long rp1dsi_refclk_freq( + return u; + } + +-static void rp1dsi_dpiclk_start(struct rp1_dsi *dsi, unsigned int bpp, unsigned int lanes) ++static void rp1dsi_dpiclk_start(struct rp1_dsi *dsi, u32 byte_clock, ++ unsigned int bpp, unsigned int lanes) + { +- unsigned long u; +- +- if (dsi->clocks[RP1DSI_CLOCK_DPI]) { +- u = (dsi->clocks[RP1DSI_CLOCK_BYTE]) ? +- clk_get_rate(dsi->clocks[RP1DSI_CLOCK_BYTE]) : 0; +- drm_info(dsi->drm, +- "rp1dsi: Nominal byte clock %lu; scale by %u/%u", +- u, 4 * lanes, (bpp >> 1)); +- if (u < 1 || u >= (1ul << 28)) +- u = 72000000ul; /* default DUMMY frequency for byteclock */ ++ /* Dummy clk_set_rate() to declare the actual DSI byte-clock rate */ ++ clk_set_rate(dsi->clocks[RP1DSI_CLOCK_BYTE], byte_clock); + ++ /* ++ * Prefer the DSI byte-clock source where possible, so that DSI and DPI ++ * clocks will be in an exact ratio and downstream devices can recover ++ * perfect timings. But when DPI clock is faster, fall back on PLL_SYS. ++ * To defeat rounding errors, specify explicitly which source to use. ++ */ ++ if (bpp >= 8 * lanes) + clk_set_parent(dsi->clocks[RP1DSI_CLOCK_DPI], dsi->clocks[RP1DSI_CLOCK_BYTE]); +- clk_set_rate(dsi->clocks[RP1DSI_CLOCK_DPI], (4 * lanes * u) / (bpp >> 1)); +- clk_prepare_enable(dsi->clocks[RP1DSI_CLOCK_DPI]); +- } ++ else if (dsi->clocks[RP1DSI_CLOCK_PLLSYS]) ++ clk_set_parent(dsi->clocks[RP1DSI_CLOCK_DPI], dsi->clocks[RP1DSI_CLOCK_PLLSYS]); ++ ++ clk_set_rate(dsi->clocks[RP1DSI_CLOCK_DPI], (4 * lanes * byte_clock) / (bpp >> 1)); ++ clk_prepare_enable(dsi->clocks[RP1DSI_CLOCK_DPI]); ++ drm_info(dsi->drm, ++ "rp1dsi: Nominal Byte clock %u DPI clock %lu (parent rate %lu)", ++ byte_clock, ++ clk_get_rate(dsi->clocks[RP1DSI_CLOCK_DPI]), ++ clk_get_rate(clk_get_parent(dsi->clocks[RP1DSI_CLOCK_DPI]))); + } + + static void rp1dsi_dpiclk_stop(struct rp1_dsi *dsi) +@@ -1336,18 +1354,21 @@ static u32 get_colorcode(enum mipi_dsi_p + return 0x005; + } + +-/* Maximum frequency for LP escape clock (20MHz), and some magic numbers */ +-#define RP1DSI_ESC_CLK_KHZ 20000 +-#define RP1DSI_TO_CLK_DIV 5 +-#define RP1DSI_HSTX_TO_MIN 0x200 +-#define RP1DSI_LPRX_TO_VAL 0x400 ++/* Frequency limits for DPI, HS and LP clocks, and some magic numbers */ ++#define RP1DSI_DPI_MAX_KHZ 200000 ++#define RP1DSI_BYTE_CLK_MIN 10000000 ++#define RP1DSI_BYTE_CLK_MAX 187500000 ++#define RP1DSI_ESC_CLK_MAX 20000000 ++#define RP1DSI_TO_CLK_DIV 0x50 ++#define RP1DSI_LPRX_TO_VAL 0x40 + #define RP1DSI_BTA_TO_VAL 0xd00 + + void rp1dsi_dsi_setup(struct rp1_dsi *dsi, struct drm_display_mode const *mode) + { + u32 timeout, mask, vid_mode_cfg; +- int lane_kbps; + unsigned int bpp = mipi_dsi_pixel_format_to_bpp(dsi->display_format); ++ u32 byte_clock = clamp((bpp * 125 * min(mode->clock, RP1DSI_DPI_MAX_KHZ)) / dsi->lanes, ++ RP1DSI_BYTE_CLK_MIN, RP1DSI_BYTE_CLK_MAX); + + DSI_WRITE(DSI_PHY_IF_CFG, dsi->lanes - 1); + DSI_WRITE(DSI_DPI_CFG_POL, 0); +@@ -1360,6 +1381,8 @@ void rp1dsi_dsi_setup(struct rp1_dsi *ds + vid_mode_cfg = 0xbf00; + if (!(dsi->display_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) + vid_mode_cfg |= 0x01; ++ else if (8 * dsi->lanes > bpp) ++ vid_mode_cfg &= ~0x400; /* PULSE && inexact DPICLK => fix HBP time */ + if (dsi->display_flags & MIPI_DSI_MODE_VIDEO_BURST) + vid_mode_cfg |= 0x02; + DSI_WRITE(DSI_VID_MODE_CFG, vid_mode_cfg); +@@ -1369,15 +1392,14 @@ void rp1dsi_dsi_setup(struct rp1_dsi *ds + DSI_WRITE(DSI_MODE_CFG, 1); + + /* Set timeouts and clock dividers */ +- DSI_WRITE(DSI_TO_CNT_CFG, +- (max((bpp * mode->htotal) / (7 * RP1DSI_TO_CLK_DIV * dsi->lanes), +- RP1DSI_HSTX_TO_MIN) << 16) | +- RP1DSI_LPRX_TO_VAL); ++ timeout = (bpp * mode->htotal * mode->vdisplay) / (7 * RP1DSI_TO_CLK_DIV * dsi->lanes); ++ if (timeout > 0xFFFFu) ++ timeout = 0; ++ DSI_WRITE(DSI_TO_CNT_CFG, (timeout << 16) | RP1DSI_LPRX_TO_VAL); + DSI_WRITE(DSI_BTA_TO_CNT, RP1DSI_BTA_TO_VAL); +- lane_kbps = (bpp * mode->clock) / dsi->lanes; + DSI_WRITE(DSI_CLKMGR_CFG, + (RP1DSI_TO_CLK_DIV << 8) | +- max(2, lane_kbps / (8 * RP1DSI_ESC_CLK_KHZ) + 1)); ++ max(2u, 1u + byte_clock / RP1DSI_ESC_CLK_MAX)); + + /* Configure video timings */ + DSI_WRITE(DSI_VID_PKT_SIZE, mode->hdisplay); +@@ -1394,7 +1416,7 @@ void rp1dsi_dsi_setup(struct rp1_dsi *ds + DSI_WRITE(DSI_VID_VACTIVE_LINES, mode->vdisplay); + + /* Init PHY */ +- dphy_init_khz(dsi, rp1dsi_refclk_freq(dsi) / 1000, lane_kbps); ++ byte_clock = dphy_init(dsi, rp1dsi_refclk_freq(dsi), 8 * byte_clock) >> 3; + + DSI_WRITE(DSI_PHY_TMR_LPCLK_CFG, + (hsfreq_table[dsi->hsfreq_index].clk_lp2hs << DSI_PHY_TMR_LP2HS_LSB) | +@@ -1418,7 +1440,7 @@ void rp1dsi_dsi_setup(struct rp1_dsi *ds + DSI_WRITE(DSI_PWR_UP, 0x1); /* power up */ + + /* Now it should be safe to start the external DPI clock divider */ +- rp1dsi_dpiclk_start(dsi, bpp, dsi->lanes); ++ rp1dsi_dpiclk_start(dsi, byte_clock, bpp, dsi->lanes); + + /* Wait for all lane(s) to be in Stopstate */ + mask = (1 << 4); diff --git a/target/linux/bcm27xx/patches-6.6/950-1180-arm64-dts-Move-bcm2712-and-rp1-here.patch b/target/linux/bcm27xx/patches-6.6/950-1180-arm64-dts-Move-bcm2712-and-rp1-here.patch new file mode 100644 index 0000000000..2856bb5cd8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1180-arm64-dts-Move-bcm2712-and-rp1-here.patch @@ -0,0 +1,9749 @@ +From 10c77e119eaaa2677009dea58cf69a8e5383925b Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 17 Jul 2024 17:27:36 +0100 +Subject: [PATCH 1180/1215] arm64: dts: Move bcm2712 and rp1 here + +It is pointless having the bcm2712 family of dts files and rp1.dtsi +in the arch/arm directory tree, since they then require placeholders +to include them in arch/arm64 where they are built. The files have +no dependencies on other files in the arch/arm tree, so simply move +them here. + +Signed-off-by: Phil Elwell +--- + .../arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts | 867 ------------------ + .../dts/broadcom/bcm2712-rpi-cm5-cm4io.dts | 20 - + .../dts/broadcom/bcm2712-rpi-cm5-cm5io.dts | 10 - + .../boot/dts/broadcom/bcm2712d0-rpi-5-b.dts | 107 --- + .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 867 +++++++++++++++++- + .../dts/broadcom/bcm2712-rpi-cm5-cm4io.dts | 20 +- + .../dts/broadcom/bcm2712-rpi-cm5-cm5io.dts | 10 +- + .../boot/dts/broadcom/bcm2712-rpi-cm5.dtsi | 10 +- + .../boot/dts/broadcom/bcm2712-rpi.dtsi | 0 + .../boot/dts/broadcom/bcm2712.dtsi | 0 + .../boot/dts/broadcom/bcm2712d0-rpi-5-b.dts | 107 ++- + .../{arm => arm64}/boot/dts/broadcom/rp1.dtsi | 0 + 12 files changed, 1002 insertions(+), 1016 deletions(-) + delete mode 100644 arch/arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts + delete mode 100644 arch/arm/boot/dts/broadcom/bcm2712-rpi-cm5-cm4io.dts + delete mode 100644 arch/arm/boot/dts/broadcom/bcm2712-rpi-cm5-cm5io.dts + delete mode 100644 arch/arm/boot/dts/broadcom/bcm2712d0-rpi-5-b.dts + rename arch/{arm => arm64}/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi (98%) + rename arch/{arm => arm64}/boot/dts/broadcom/bcm2712-rpi.dtsi (100%) + rename arch/{arm => arm64}/boot/dts/broadcom/bcm2712.dtsi (100%) + rename arch/{arm => arm64}/boot/dts/broadcom/rp1.dtsi (100%) + +--- a/arch/arm/boot/dts/broadcom/bcm2712-rpi-5-b.dts ++++ /dev/null +@@ -1,867 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/dts-v1/; +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define i2c0 _i2c0 +-#define i2c3 _i2c3 +-#define i2c4 _i2c4 +-#define i2c5 _i2c5 +-#define i2c6 _i2c6 +-#define i2c8 _i2c8 +-#define i2s _i2s +-#define pwm0 _pwm0 +-#define pwm1 _pwm1 +-#define spi0 _spi0 +-#define spi3 _spi3 +-#define spi4 _spi4 +-#define spi5 _spi5 +-#define spi6 _spi6 +-#define uart0 _uart0 +-#define uart2 _uart2 +-#define uart5 _uart5 +- +-#include "bcm2712.dtsi" +- +-#undef i2c0 +-#undef i2c3 +-#undef i2c4 +-#undef i2c5 +-#undef i2c6 +-#undef i2c8 +-#undef i2s +-#undef pwm0 +-#undef pwm1 +-#undef spi0 +-#undef spi3 +-#undef spi4 +-#undef spi5 +-#undef spi6 +-#undef uart0 +-#undef uart2 +-#undef uart3 +-#undef uart4 +-#undef uart5 +- +-/ { +- compatible = "raspberrypi,5-model-b", "brcm,bcm2712"; +- model = "Raspberry Pi 5"; +- +- /* Will be filled by the bootloader */ +- memory@0 { +- device_type = "memory"; +- reg = <0 0 0x28000000>; +- }; +- +- leds: leds { +- compatible = "gpio-leds"; +- +- led_pwr: led-pwr { +- label = "PWR"; +- gpios = <&rp1_gpio 44 GPIO_ACTIVE_LOW>; +- default-state = "off"; +- linux,default-trigger = "none"; +- }; +- +- led_act: led-act { +- label = "ACT"; +- gpios = <&gio_aon 9 GPIO_ACTIVE_LOW>; +- default-state = "off"; +- linux,default-trigger = "mmc0"; +- }; +- }; +- +- sd_io_1v8_reg: sd_io_1v8_reg { +- compatible = "regulator-gpio"; +- regulator-name = "vdd-sd-io"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <3300000>; +- regulator-boot-on; +- regulator-always-on; +- regulator-settling-time-us = <5000>; +- gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>; +- states = <1800000 0x1 +- 3300000 0x0>; +- status = "okay"; +- }; +- +- sd_vcc_reg: sd_vcc_reg { +- compatible = "regulator-fixed"; +- regulator-name = "vcc-sd"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-boot-on; +- enable-active-high; +- gpios = <&gio_aon 4 GPIO_ACTIVE_HIGH>; +- status = "okay"; +- }; +- +- wl_on_reg: wl_on_reg { +- compatible = "regulator-fixed"; +- regulator-name = "wl-on-regulator"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- pinctrl-0 = <&wl_on_pins>; +- pinctrl-names = "default"; +- +- gpio = <&gio 28 GPIO_ACTIVE_HIGH>; +- +- startup-delay-us = <150000>; +- enable-active-high; +- }; +- +- clocks: clocks { +- }; +- +- cam1_clk: cam1_clk { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- status = "disabled"; +- }; +- +- cam0_clk: cam0_clk { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- status = "disabled"; +- }; +- +- cam0_reg: cam0_reg { +- compatible = "regulator-fixed"; +- regulator-name = "cam0_reg"; +- enable-active-high; +- status = "okay"; +- gpio = <&rp1_gpio 34 0>; // CD0_IO0_MICCLK, to MIPI 0 connector +- }; +- +- cam1_reg: cam1_reg { +- compatible = "regulator-fixed"; +- regulator-name = "cam1_reg"; +- enable-active-high; +- status = "okay"; +- gpio = <&rp1_gpio 46 0>; // CD1_IO0_MICCLK, to MIPI 1 connector +- }; +- +- cam_dummy_reg: cam_dummy_reg { +- compatible = "regulator-fixed"; +- regulator-name = "cam-dummy-reg"; +- status = "okay"; +- }; +- +- dummy: dummy { +- // A target for unwanted overlay fragments +- }; +- +- +- // A few extra labels to keep overlays happy +- +- i2c0if: i2c0if {}; +- i2c0mux: i2c0mux {}; +-}; +- +-rp1_target: &pcie2 { +- brcm,enable-mps-rcb; +- brcm,vdm-qos-map = <0xbbaa9888>; +- aspm-no-l0s; +- status = "okay"; +-}; +- +-&pcie1 { +- brcm,vdm-qos-map = <0x33333333>; +-}; +- +-// Add some labels to 2712 device +- +-// The system UART +-uart10: &_uart0 { status = "okay"; }; +- +-// The system SPI for the bootloader EEPROM +-spi10: &_spi0 { status = "okay"; }; +- +-i2c_rp1boot: &_i2c3 { }; +- +-#include "rp1.dtsi" +- +-&rp1 { +- // PCIe address space layout: +- // 00_00000000-00_00xxxxxx = RP1 peripherals +- // 10_00000000-1x_xxxxxxxx = up to 64GB system RAM +- +- // outbound access aimed at PCIe 0_00xxxxxx -> RP1 c0_40xxxxxx +- // This is the RP1 peripheral space +- ranges = <0xc0 0x40000000 +- 0x02000000 0x00 0x00000000 +- 0x00 0x00400000>; +- +- dma-ranges = +- // inbound RP1 1x_xxxxxxxx -> PCIe 1x_xxxxxxxx +- <0x10 0x00000000 +- 0x43000000 0x10 0x00000000 +- 0x10 0x00000000>, +- +- // inbound RP1 c0_40xxxxxx -> PCIe 00_00xxxxxx +- // This allows the RP1 DMA controller to address RP1 hardware +- <0xc0 0x40000000 +- 0x02000000 0x0 0x00000000 +- 0x0 0x00400000>, +- +- // inbound RP1 0x_xxxxxxxx -> PCIe 1x_xxxxxxxx +- <0x00 0x00000000 +- 0x02000000 0x10 0x00000000 +- 0x10 0x00000000>; +-}; +- +-// Expose RP1 nodes as system nodes with labels +- +-&rp1_dma { +- status = "okay"; +-}; +- +-&rp1_eth { +- status = "okay"; +- phy-handle = <&phy1>; +- phy-reset-gpios = <&rp1_gpio 32 GPIO_ACTIVE_LOW>; +- phy-reset-duration = <5>; +- +- phy1: ethernet-phy@1 { +- reg = <0x1>; +- brcm,powerdown-enable; +- }; +-}; +- +-gpio: &rp1_gpio { +- status = "okay"; +-}; +- +-aux: &dummy {}; +- +-&rp1_usb0 { +- pinctrl-0 = <&usb_vbus_pins>; +- pinctrl-names = "default"; +- status = "okay"; +-}; +- +-&rp1_usb1 { +- status = "okay"; +-}; +- +-#include "bcm2712-rpi.dtsi" +- +-i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only +- pinctrl-0 = <&rp1_i2c6_38_39>; +- pinctrl-names = "default"; +- clock-frequency = <100000>; +-}; +- +-i2c_csi_dsi1: &i2c4 { // Note: This is for MIPI1 connector only +- pinctrl-0 = <&rp1_i2c4_40_41>; +- pinctrl-names = "default"; +- clock-frequency = <100000>; +-}; +- +-i2c_csi_dsi: &i2c_csi_dsi1 { }; // An alias for compatibility +- +-csi0: &rp1_csi0 { }; +-csi1: &rp1_csi1 { }; +-dsi0: &rp1_dsi0 { }; +-dsi1: &rp1_dsi1 { }; +-dpi: &rp1_dpi { }; +-vec: &rp1_vec { }; +-dpi_gpio0: &rp1_dpi_24bit_gpio0 { }; +-dpi_gpio1: &rp1_dpi_24bit_gpio2 { }; +-dpi_18bit_cpadhi_gpio0: &rp1_dpi_18bit_cpadhi_gpio0 { }; +-dpi_18bit_cpadhi_gpio2: &rp1_dpi_18bit_cpadhi_gpio2 { }; +-dpi_18bit_gpio0: &rp1_dpi_18bit_gpio0 { }; +-dpi_18bit_gpio2: &rp1_dpi_18bit_gpio2 { }; +-dpi_16bit_cpadhi_gpio0: &rp1_dpi_16bit_cpadhi_gpio0 { }; +-dpi_16bit_cpadhi_gpio2: &rp1_dpi_16bit_cpadhi_gpio2 { }; +-dpi_16bit_gpio0: &rp1_dpi_16bit_gpio0 { }; +-dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; +- +-/* Add the IOMMUs for some RP1 bus masters */ +- +-&csi0 { +- iommus = <&iommu5>; +-}; +- +-&csi1 { +- iommus = <&iommu5>; +-}; +- +-&dsi0 { +- iommus = <&iommu5>; +-}; +- +-&dsi1 { +- iommus = <&iommu5>; +-}; +- +-&dpi { +- iommus = <&iommu5>; +-}; +- +-&vec { +- iommus = <&iommu5>; +-}; +- +-&ddc0 { +- status = "disabled"; +-}; +- +-&ddc1 { +- status = "disabled"; +-}; +- +-&hdmi0 { +- clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>; +- clock-names = "hdmi", "bvb", "audio", "cec"; +- status = "disabled"; +-}; +- +-&hdmi1 { +- clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; +- clock-names = "hdmi", "bvb", "audio", "cec"; +- status = "disabled"; +-}; +- +-&hvs { +- clocks = <&firmware_clocks 4>, <&firmware_clocks 16>; +- clock-names = "core", "disp"; +-}; +- +-&mop { +- status = "disabled"; +-}; +- +-&moplet { +- status = "disabled"; +-}; +- +-&pixelvalve0 { +- status = "disabled"; +-}; +- +-&pixelvalve1 { +- status = "disabled"; +-}; +- +-&disp_intr { +- status = "disabled"; +-}; +- +-/* SDIO1 is used to drive the SD card */ +-&sdio1 { +- pinctrl-0 = <&emmc_sd_pulls>, <&emmc_aon_cd_pins>; +- pinctrl-names = "default"; +- vqmmc-supply = <&sd_io_1v8_reg>; +- vmmc-supply = <&sd_vcc_reg>; +- bus-width = <4>; +- sd-uhs-sdr50; +- sd-uhs-ddr50; +- sd-uhs-sdr104; +- cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>; +- //no-1-8-v; +- status = "okay"; +-}; +- +-&pinctrl_aon { +- emmc_aon_cd_pins: emmc_aon_cd_pins { +- function = "sd_card_g"; +- pins = "aon_gpio5"; +- bias-pull-up; +- }; +- +- /* Slight hack - only one PWM pin (status LED) is usable */ +- aon_pwm_1pin: aon_pwm_1pin { +- function = "aon_pwm"; +- pins = "aon_gpio9"; +- }; +-}; +- +-&pinctrl { +- pwr_button_pins: pwr_button_pins { +- function = "gpio"; +- pins = "gpio20"; +- bias-pull-up; +- }; +- +- wl_on_pins: wl_on_pins { +- function = "gpio"; +- pins = "gpio28"; +- }; +- +- bt_shutdown_pins: bt_shutdown_pins { +- function = "gpio"; +- pins = "gpio29"; +- }; +- +- emmc_sd_pulls: emmc_sd_pulls { +- pins = "emmc_cmd", "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3"; +- bias-pull-up; +- }; +-}; +- +-/* uarta communicates with the BT module */ +-&uarta { +- uart-has-rtscts; +- auto-flow-control; +- status = "okay"; +- clock-frequency = <96000000>; +- pinctrl-0 = <&uarta_24_pins &bt_shutdown_pins>; +- pinctrl-names = "default"; +- +- bluetooth: bluetooth { +- compatible = "brcm,bcm43438-bt"; +- max-speed = <3000000>; +- shutdown-gpios = <&gio 29 GPIO_ACTIVE_HIGH>; +- local-bd-address = [ 00 00 00 00 00 00 ]; +- }; +-}; +- +-&i2c_rp1boot { +- clock-frequency = <400000>; +- pinctrl-0 = <&i2c3_m4_agpio0_pins>; +- pinctrl-names = "default"; +-}; +- +-/ { +- chosen: chosen { +- bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe"; +- stdout-path = "serial10:115200n8"; +- }; +- +- fan: cooling_fan { +- status = "disabled"; +- compatible = "pwm-fan"; +- #cooling-cells = <2>; +- cooling-min-state = <0>; +- cooling-max-state = <3>; +- cooling-levels = <0 75 125 175 250>; +- pwms = <&rp1_pwm1 3 41566 PWM_POLARITY_INVERTED>; +- rpm-regmap = <&rp1_pwm1>; +- rpm-offset = <0x3c>; +- }; +- +- pwr_button { +- compatible = "gpio-keys"; +- +- pinctrl-names = "default"; +- pinctrl-0 = <&pwr_button_pins>; +- status = "okay"; +- +- pwr_key: pwr { +- label = "pwr_button"; +- // linux,code = <205>; // KEY_SUSPEND +- linux,code = <116>; // KEY_POWER +- gpios = <&gio 20 GPIO_ACTIVE_LOW>; +- debounce-interval = <50>; // ms +- }; +- }; +-}; +- +-&usb { +- power-domains = <&power RPI_POWER_DOMAIN_USB>; +-}; +- +-/* SDIO2 drives the WLAN interface */ +-&sdio2 { +- pinctrl-0 = <&sdio2_30_pins>; +- pinctrl-names = "default"; +- bus-width = <4>; +- vmmc-supply = <&wl_on_reg>; +- sd-uhs-ddr50; +- non-removable; +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- +- wifi: wifi@1 { +- reg = <1>; +- compatible = "brcm,bcm4329-fmac"; +- local-mac-address = [00 00 00 00 00 00]; +- }; +-}; +- +-&rpivid { +- status = "okay"; +-}; +- +-&pinctrl { +- spi10_gpio2: spi10_gpio2 { +- function = "vc_spi0"; +- pins = "gpio2", "gpio3", "gpio4"; +- bias-disable; +- }; +- +- spi10_cs_gpio1: spi10_cs_gpio1 { +- function = "gpio"; +- pins = "gpio1"; +- bias-pull-up; +- }; +-}; +- +-spi10_pins: &spi10_gpio2 {}; +-spi10_cs_pins: &spi10_cs_gpio1 {}; +- +-&spi10 { +- pinctrl-names = "default"; +- cs-gpios = <&gio 1 1>; +- pinctrl-0 = <&spi10_pins &spi10_cs_pins>; +- +- spidev10: spidev@0 { +- compatible = "spidev"; +- reg = <0>; /* CE0 */ +- #address-cells = <1>; +- #size-cells = <0>; +- spi-max-frequency = <20000000>; +- status = "okay"; +- }; +-}; +- +-// ============================================= +-// Board specific stuff here +- +-&gio_aon { +- // Don't use GIO_AON as an interrupt controller because it will +- // clash with the firmware monitoring the PMIC interrupt via the VPU. +- +- /delete-property/ interrupt-controller; +-}; +- +-&main_aon_irq { +- // Don't use the MAIN_AON_IRQ interrupt controller because it will +- // clash with the firmware monitoring the PMIC interrupt via the VPU. +- +- status = "disabled"; +-}; +- +-&rp1_pwm1 { +- status = "disabled"; +- pinctrl-0 = <&rp1_pwm1_gpio45>; +- pinctrl-names = "default"; +-}; +- +-&thermal_trips { +- cpu_tepid: cpu-tepid { +- temperature = <50000>; +- hysteresis = <5000>; +- type = "active"; +- }; +- +- cpu_warm: cpu-warm { +- temperature = <60000>; +- hysteresis = <5000>; +- type = "active"; +- }; +- +- cpu_hot: cpu-hot { +- temperature = <67500>; +- hysteresis = <5000>; +- type = "active"; +- }; +- +- cpu_vhot: cpu-vhot { +- temperature = <75000>; +- hysteresis = <5000>; +- type = "active"; +- }; +-}; +- +-&cooling_maps { +- tepid { +- trip = <&cpu_tepid>; +- cooling-device = <&fan 1 1>; +- }; +- +- warm { +- trip = <&cpu_warm>; +- cooling-device = <&fan 2 2>; +- }; +- +- hot { +- trip = <&cpu_hot>; +- cooling-device = <&fan 3 3>; +- }; +- +- vhot { +- trip = <&cpu_vhot>; +- cooling-device = <&fan 4 4>; +- }; +- +- melt { +- trip = <&cpu_crit>; +- cooling-device = <&fan 4 4>; +- }; +-}; +- +-&gio { +- // The GPIOs above 35 are not used on Pi 5, so shrink the upper bank +- // to reduce the clutter in gpioinfo/pinctrl +- brcm,gpio-bank-widths = <32 4>; +- +- gpio-line-names = +- "-", // GPIO_000 +- "2712_BOOT_CS_N", // GPIO_001 +- "2712_BOOT_MISO", // GPIO_002 +- "2712_BOOT_MOSI", // GPIO_003 +- "2712_BOOT_SCLK", // GPIO_004 +- "-", // GPIO_005 +- "-", // GPIO_006 +- "-", // GPIO_007 +- "-", // GPIO_008 +- "-", // GPIO_009 +- "-", // GPIO_010 +- "-", // GPIO_011 +- "-", // GPIO_012 +- "-", // GPIO_013 +- "PCIE_SDA", // GPIO_014 +- "PCIE_SCL", // GPIO_015 +- "-", // GPIO_016 +- "-", // GPIO_017 +- "-", // GPIO_018 +- "-", // GPIO_019 +- "PWR_GPIO", // GPIO_020 +- "2712_G21_FS", // GPIO_021 +- "-", // GPIO_022 +- "-", // GPIO_023 +- "BT_RTS", // GPIO_024 +- "BT_CTS", // GPIO_025 +- "BT_TXD", // GPIO_026 +- "BT_RXD", // GPIO_027 +- "WL_ON", // GPIO_028 +- "BT_ON", // GPIO_029 +- "WIFI_SDIO_CLK", // GPIO_030 +- "WIFI_SDIO_CMD", // GPIO_031 +- "WIFI_SDIO_D0", // GPIO_032 +- "WIFI_SDIO_D1", // GPIO_033 +- "WIFI_SDIO_D2", // GPIO_034 +- "WIFI_SDIO_D3"; // GPIO_035 +-}; +- +-&gio_aon { +- gpio-line-names = +- "RP1_SDA", // AON_GPIO_00 +- "RP1_SCL", // AON_GPIO_01 +- "RP1_RUN", // AON_GPIO_02 +- "SD_IOVDD_SEL", // AON_GPIO_03 +- "SD_PWR_ON", // AON_GPIO_04 +- "SD_CDET_N", // AON_GPIO_05 +- "SD_FLG_N", // AON_GPIO_06 +- "-", // AON_GPIO_07 +- "2712_WAKE", // AON_GPIO_08 +- "2712_STAT_LED", // AON_GPIO_09 +- "-", // AON_GPIO_10 +- "-", // AON_GPIO_11 +- "PMIC_INT", // AON_GPIO_12 +- "UART_TX_FS", // AON_GPIO_13 +- "UART_RX_FS", // AON_GPIO_14 +- "-", // AON_GPIO_15 +- "-", // AON_GPIO_16 +- +- // Pad bank0 out to 32 entries +- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", +- +- "HDMI0_SCL", // AON_SGPIO_00 +- "HDMI0_SDA", // AON_SGPIO_01 +- "HDMI1_SCL", // AON_SGPIO_02 +- "HDMI1_SDA", // AON_SGPIO_03 +- "PMIC_SCL", // AON_SGPIO_04 +- "PMIC_SDA"; // AON_SGPIO_05 +- +- rp1_run_hog { +- gpio-hog; +- gpios = <2 GPIO_ACTIVE_HIGH>; +- output-high; +- line-name = "RP1 RUN pin"; +- }; +-}; +- +-&rp1_gpio { +- gpio-line-names = +- "ID_SDA", // GPIO0 +- "ID_SCL", // GPIO1 +- "GPIO2", // GPIO2 +- "GPIO3", // GPIO3 +- "GPIO4", // GPIO4 +- "GPIO5", // GPIO5 +- "GPIO6", // GPIO6 +- "GPIO7", // GPIO7 +- "GPIO8", // GPIO8 +- "GPIO9", // GPIO9 +- "GPIO10", // GPIO10 +- "GPIO11", // GPIO11 +- "GPIO12", // GPIO12 +- "GPIO13", // GPIO13 +- "GPIO14", // GPIO14 +- "GPIO15", // GPIO15 +- "GPIO16", // GPIO16 +- "GPIO17", // GPIO17 +- "GPIO18", // GPIO18 +- "GPIO19", // GPIO19 +- "GPIO20", // GPIO20 +- "GPIO21", // GPIO21 +- "GPIO22", // GPIO22 +- "GPIO23", // GPIO23 +- "GPIO24", // GPIO24 +- "GPIO25", // GPIO25 +- "GPIO26", // GPIO26 +- "GPIO27", // GPIO27 +- +- "PCIE_RP1_WAKE", // GPIO28 +- "FAN_TACH", // GPIO29 +- "HOST_SDA", // GPIO30 +- "HOST_SCL", // GPIO31 +- "ETH_RST_N", // GPIO32 +- "-", // GPIO33 +- +- "CD0_IO0_MICCLK", // GPIO34 +- "CD0_IO0_MICDAT0", // GPIO35 +- "RP1_PCIE_CLKREQ_N", // GPIO36 +- "-", // GPIO37 +- "CD0_SDA", // GPIO38 +- "CD0_SCL", // GPIO39 +- "CD1_SDA", // GPIO40 +- "CD1_SCL", // GPIO41 +- "USB_VBUS_EN", // GPIO42 +- "USB_OC_N", // GPIO43 +- "RP1_STAT_LED", // GPIO44 +- "FAN_PWM", // GPIO45 +- "CD1_IO0_MICCLK", // GPIO46 +- "2712_WAKE", // GPIO47 +- "CD1_IO1_MICDAT1", // GPIO48 +- "EN_MAX_USB_CUR", // GPIO49 +- "-", // GPIO50 +- "-", // GPIO51 +- "-", // GPIO52 +- "-"; // GPIO53 +- +- usb_vbus_pins: usb_vbus_pins { +- function = "vbus1"; +- pins = "gpio42", "gpio43"; +- }; +-}; +- +-/ { +- aliases: aliases { +- blconfig = &blconfig; +- blpubkey = &blpubkey; +- bluetooth = &bluetooth; +- console = &uart10; +- ethernet0 = &rp1_eth; +- wifi0 = &wifi; +- fb = &fb; +- mailbox = &mailbox; +- mmc0 = &sdio1; +- uart0 = &uart0; +- uart1 = &uart1; +- uart2 = &uart2; +- uart3 = &uart3; +- uart4 = &uart4; +- uart10 = &uart10; +- serial0 = &uart0; +- serial1 = &uart1; +- serial2 = &uart2; +- serial3 = &uart3; +- serial4 = &uart4; +- serial10 = &uart10; +- i2c = &i2c_arm; +- i2c0 = &i2c0; +- i2c1 = &i2c1; +- i2c2 = &i2c2; +- i2c3 = &i2c3; +- i2c4 = &i2c4; +- i2c5 = &i2c5; +- i2c6 = &i2c6; +- i2c10 = &i2c_rp1boot; +- // Bit-bashed i2c_gpios start at 10 +- spi0 = &spi0; +- spi1 = &spi1; +- spi2 = &spi2; +- spi3 = &spi3; +- spi4 = &spi4; +- spi5 = &spi5; +- spi10 = &spi10; +- gpio0 = &gpio; +- gpio1 = &gio; +- gpio2 = &gio_aon; +- gpio3 = &pinctrl; +- gpio4 = &pinctrl_aon; +- usb0 = &rp1_usb0; +- usb1 = &rp1_usb1; +- drm-dsi1 = &dsi0; +- drm-dsi2 = &dsi1; +- }; +- +- __overrides__ { +- bdaddr = <&bluetooth>, "local-bd-address["; +- button_debounce = <&pwr_key>, "debounce-interval:0"; +- cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status"; +- uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0; +- i2c0 = <&i2c0>, "status"; +- i2c1 = <&i2c1>, "status"; +- i2c = <&i2c1>, "status"; +- i2c_arm = <&i2c_arm>, "status"; +- i2c_vc = <&i2c_vc>, "status"; +- i2c_csi_dsi = <&i2c_csi_dsi>, "status"; +- i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status"; +- i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status"; +- i2c0_baudrate = <&i2c0>, "clock-frequency:0"; +- i2c1_baudrate = <&i2c1>, "clock-frequency:0"; +- i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; +- i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; +- i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; +- krnbt = <&bluetooth>, "status"; +- nvme = <&pciex1>, "status"; +- pciex1 = <&pciex1>, "status"; +- pciex1_gen = <&pciex1> , "max-link-speed:0"; +- pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; +- pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; +- pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; +- random = <&random>, "status"; +- rtc = <&rpi_rtc>, "status"; +- rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; +- sd_cqe = <&sdio1>, "supports-cqe?"; +- spi = <&spi0>, "status"; +- suspend = <&pwr_key>, "linux,code:0=205"; +- uart0 = <&uart0>, "status"; +- wifiaddr = <&wifi>, "local-mac-address["; +- +- act_led_gpio = <&led_act>,"gpios:4",<&led_act>,"gpios:0=",<&gpio>; +- act_led_activelow = <&led_act>,"gpios:8"; +- act_led_trigger = <&led_act>, "linux,default-trigger"; +- pwr_led_gpio = <&led_pwr>,"gpios:4"; +- pwr_led_activelow = <&led_pwr>, "gpios:8"; +- pwr_led_trigger = <&led_pwr>, "linux,default-trigger"; +- eth_led0 = <&phy1>,"led-modes:0"; +- eth_led1 = <&phy1>,"led-modes:4"; +- drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; +- drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; +- drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; +- drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; +- drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0; +- drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1; +- drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi; +- drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; +- drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0; +- drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; +- drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; +- drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; +- +- fan_temp0 = <&cpu_tepid>,"temperature:0"; +- fan_temp1 = <&cpu_warm>,"temperature:0"; +- fan_temp2 = <&cpu_hot>,"temperature:0"; +- fan_temp3 = <&cpu_vhot>,"temperature:0"; +- fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0"; +- fan_temp1_hyst = <&cpu_warm>,"hysteresis:0"; +- fan_temp2_hyst = <&cpu_hot>,"hysteresis:0"; +- fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0"; +- fan_temp0_speed = <&fan>, "cooling-levels:4"; +- fan_temp1_speed = <&fan>, "cooling-levels:8"; +- fan_temp2_speed = <&fan>, "cooling-levels:12"; +- fan_temp3_speed = <&fan>, "cooling-levels:16"; +- }; +-}; +--- a/arch/arm/boot/dts/broadcom/bcm2712-rpi-cm5-cm4io.dts ++++ /dev/null +@@ -1,20 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/dts-v1/; +- +-#include "bcm2712-rpi-cm5.dtsi" +- +-// The RP1 USB3 interfaces are not usable on CM4IO +- +-&rp1_usb0 { +- status = "disabled"; +-}; +- +-&rp1_usb1 { +- status = "disabled"; +-}; +- +-/ { +- __overrides__ { +- i2c_csi_dsi = <&i2c_csi_dsi>, "status"; +- }; +-}; +--- a/arch/arm/boot/dts/broadcom/bcm2712-rpi-cm5-cm5io.dts ++++ /dev/null +@@ -1,10 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/dts-v1/; +- +-#include "bcm2712-rpi-cm5.dtsi" +- +-/ { +- __overrides__ { +- i2c_csi_dsi = <&i2c_csi_dsi>, "status"; +- }; +-}; +--- a/arch/arm/boot/dts/broadcom/bcm2712d0-rpi-5-b.dts ++++ /dev/null +@@ -1,107 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-#include "bcm2712-rpi-5-b.dts" +- +-&gio { +- brcm,gpio-bank-widths = <32 4>; +- +- gpio-line-names = +- "", // GPIO_000 +- "2712_BOOT_CS_N", // GPIO_001 +- "2712_BOOT_MISO", // GPIO_002 +- "2712_BOOT_MOSI", // GPIO_003 +- "2712_BOOT_SCLK", // GPIO_004 +- "", // GPIO_005 +- "", // GPIO_006 +- "", // GPIO_007 +- "", // GPIO_008 +- "", // GPIO_009 +- "", // GPIO_010 +- "", // GPIO_011 +- "", // GPIO_012 +- "", // GPIO_013 +- "PCIE_SDA", // GPIO_014 +- "PCIE_SCL", // GPIO_015 +- "", // GPIO_016 +- "", // GPIO_017 +- "-", // GPIO_018 +- "-", // GPIO_019 +- "PWR_GPIO", // GPIO_020 +- "2712_G21_FS", // GPIO_021 +- "-", // GPIO_022 +- "-", // GPIO_023 +- "BT_RTS", // GPIO_024 +- "BT_CTS", // GPIO_025 +- "BT_TXD", // GPIO_026 +- "BT_RXD", // GPIO_027 +- "WL_ON", // GPIO_028 +- "BT_ON", // GPIO_029 +- "WIFI_SDIO_CLK", // GPIO_030 +- "WIFI_SDIO_CMD", // GPIO_031 +- "WIFI_SDIO_D0", // GPIO_032 +- "WIFI_SDIO_D1", // GPIO_033 +- "WIFI_SDIO_D2", // GPIO_034 +- "WIFI_SDIO_D3"; // GPIO_035 +-}; +- +-&gio_aon { +- brcm,gpio-bank-widths = <15 6>; +- +- gpio-line-names = +- "RP1_SDA", // AON_GPIO_00 +- "RP1_SCL", // AON_GPIO_01 +- "RP1_RUN", // AON_GPIO_02 +- "SD_IOVDD_SEL", // AON_GPIO_03 +- "SD_PWR_ON", // AON_GPIO_04 +- "SD_CDET_N", // AON_GPIO_05 +- "SD_FLG_N", // AON_GPIO_06 +- "", // AON_GPIO_07 +- "2712_WAKE", // AON_GPIO_08 +- "2712_STAT_LED", // AON_GPIO_09 +- "", // AON_GPIO_10 +- "", // AON_GPIO_11 +- "PMIC_INT", // AON_GPIO_12 +- "UART_TX_FS", // AON_GPIO_13 +- "UART_RX_FS", // AON_GPIO_14 +- "", // AON_GPIO_15 +- "", // AON_GPIO_16 +- +- // Pad bank0 out to 32 entries +- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", +- +- "HDMI0_SCL", // AON_SGPIO_00 +- "HDMI0_SDA", // AON_SGPIO_01 +- "HDMI1_SCL", // AON_SGPIO_02 +- "HDMI1_SDA", // AON_SGPIO_03 +- "PMIC_SCL", // AON_SGPIO_04 +- "PMIC_SDA"; // AON_SGPIO_05 +-}; +- +-&pinctrl { +- compatible = "brcm,bcm2712d0-pinctrl"; +- reg = <0x7d504100 0x20>; +-}; +- +-&pinctrl_aon { +- compatible = "brcm,bcm2712d0-aon-pinctrl"; +- reg = <0x7d510700 0x1c>; +-}; +- +-&vc4 { +- compatible = "brcm,bcm2712d0-vc6"; +-}; +- +-&uart10 { +- interrupts = ; +-}; +- +-&spi10 { +- dmas = <&dma40 3>, <&dma40 4>; +-}; +- +-&hdmi0 { +- dmas = <&dma40 (12|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; +-}; +- +-&hdmi1 { +- dmas = <&dma40 (13|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; +-}; +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +@@ -1,2 +1,867 @@ + // SPDX-License-Identifier: GPL-2.0 +-#include "arm/broadcom/bcm2712-rpi-5-b.dts" ++/dts-v1/; ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define i2c0 _i2c0 ++#define i2c3 _i2c3 ++#define i2c4 _i2c4 ++#define i2c5 _i2c5 ++#define i2c6 _i2c6 ++#define i2c8 _i2c8 ++#define i2s _i2s ++#define pwm0 _pwm0 ++#define pwm1 _pwm1 ++#define spi0 _spi0 ++#define spi3 _spi3 ++#define spi4 _spi4 ++#define spi5 _spi5 ++#define spi6 _spi6 ++#define uart0 _uart0 ++#define uart2 _uart2 ++#define uart5 _uart5 ++ ++#include "bcm2712.dtsi" ++ ++#undef i2c0 ++#undef i2c3 ++#undef i2c4 ++#undef i2c5 ++#undef i2c6 ++#undef i2c8 ++#undef i2s ++#undef pwm0 ++#undef pwm1 ++#undef spi0 ++#undef spi3 ++#undef spi4 ++#undef spi5 ++#undef spi6 ++#undef uart0 ++#undef uart2 ++#undef uart3 ++#undef uart4 ++#undef uart5 ++ ++/ { ++ compatible = "raspberrypi,5-model-b", "brcm,bcm2712"; ++ model = "Raspberry Pi 5"; ++ ++ /* Will be filled by the bootloader */ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0 0 0x28000000>; ++ }; ++ ++ leds: leds { ++ compatible = "gpio-leds"; ++ ++ led_pwr: led-pwr { ++ label = "PWR"; ++ gpios = <&rp1_gpio 44 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "none"; ++ }; ++ ++ led_act: led-act { ++ label = "ACT"; ++ gpios = <&gio_aon 9 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ sd_io_1v8_reg: sd_io_1v8_reg { ++ compatible = "regulator-gpio"; ++ regulator-name = "vdd-sd-io"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-settling-time-us = <5000>; ++ gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>; ++ states = <1800000 0x1 ++ 3300000 0x0>; ++ status = "okay"; ++ }; ++ ++ sd_vcc_reg: sd_vcc_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ enable-active-high; ++ gpios = <&gio_aon 4 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wl_on_reg: wl_on_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "wl-on-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ pinctrl-0 = <&wl_on_pins>; ++ pinctrl-names = "default"; ++ ++ gpio = <&gio 28 GPIO_ACTIVE_HIGH>; ++ ++ startup-delay-us = <150000>; ++ enable-active-high; ++ }; ++ ++ clocks: clocks { ++ }; ++ ++ cam1_clk: cam1_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ cam0_clk: cam0_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ cam0_reg: cam0_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam0_reg"; ++ enable-active-high; ++ status = "okay"; ++ gpio = <&rp1_gpio 34 0>; // CD0_IO0_MICCLK, to MIPI 0 connector ++ }; ++ ++ cam1_reg: cam1_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam1_reg"; ++ enable-active-high; ++ status = "okay"; ++ gpio = <&rp1_gpio 46 0>; // CD1_IO0_MICCLK, to MIPI 1 connector ++ }; ++ ++ cam_dummy_reg: cam_dummy_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam-dummy-reg"; ++ status = "okay"; ++ }; ++ ++ dummy: dummy { ++ // A target for unwanted overlay fragments ++ }; ++ ++ ++ // A few extra labels to keep overlays happy ++ ++ i2c0if: i2c0if {}; ++ i2c0mux: i2c0mux {}; ++}; ++ ++rp1_target: &pcie2 { ++ brcm,enable-mps-rcb; ++ brcm,vdm-qos-map = <0xbbaa9888>; ++ aspm-no-l0s; ++ status = "okay"; ++}; ++ ++&pcie1 { ++ brcm,vdm-qos-map = <0x33333333>; ++}; ++ ++// Add some labels to 2712 device ++ ++// The system UART ++uart10: &_uart0 { status = "okay"; }; ++ ++// The system SPI for the bootloader EEPROM ++spi10: &_spi0 { status = "okay"; }; ++ ++i2c_rp1boot: &_i2c3 { }; ++ ++#include "rp1.dtsi" ++ ++&rp1 { ++ // PCIe address space layout: ++ // 00_00000000-00_00xxxxxx = RP1 peripherals ++ // 10_00000000-1x_xxxxxxxx = up to 64GB system RAM ++ ++ // outbound access aimed at PCIe 0_00xxxxxx -> RP1 c0_40xxxxxx ++ // This is the RP1 peripheral space ++ ranges = <0xc0 0x40000000 ++ 0x02000000 0x00 0x00000000 ++ 0x00 0x00400000>; ++ ++ dma-ranges = ++ // inbound RP1 1x_xxxxxxxx -> PCIe 1x_xxxxxxxx ++ <0x10 0x00000000 ++ 0x43000000 0x10 0x00000000 ++ 0x10 0x00000000>, ++ ++ // inbound RP1 c0_40xxxxxx -> PCIe 00_00xxxxxx ++ // This allows the RP1 DMA controller to address RP1 hardware ++ <0xc0 0x40000000 ++ 0x02000000 0x0 0x00000000 ++ 0x0 0x00400000>, ++ ++ // inbound RP1 0x_xxxxxxxx -> PCIe 1x_xxxxxxxx ++ <0x00 0x00000000 ++ 0x02000000 0x10 0x00000000 ++ 0x10 0x00000000>; ++}; ++ ++// Expose RP1 nodes as system nodes with labels ++ ++&rp1_dma { ++ status = "okay"; ++}; ++ ++&rp1_eth { ++ status = "okay"; ++ phy-handle = <&phy1>; ++ phy-reset-gpios = <&rp1_gpio 32 GPIO_ACTIVE_LOW>; ++ phy-reset-duration = <5>; ++ ++ phy1: ethernet-phy@1 { ++ reg = <0x1>; ++ brcm,powerdown-enable; ++ }; ++}; ++ ++gpio: &rp1_gpio { ++ status = "okay"; ++}; ++ ++aux: &dummy {}; ++ ++&rp1_usb0 { ++ pinctrl-0 = <&usb_vbus_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&rp1_usb1 { ++ status = "okay"; ++}; ++ ++#include "bcm2712-rpi.dtsi" ++ ++i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only ++ pinctrl-0 = <&rp1_i2c6_38_39>; ++ pinctrl-names = "default"; ++ clock-frequency = <100000>; ++}; ++ ++i2c_csi_dsi1: &i2c4 { // Note: This is for MIPI1 connector only ++ pinctrl-0 = <&rp1_i2c4_40_41>; ++ pinctrl-names = "default"; ++ clock-frequency = <100000>; ++}; ++ ++i2c_csi_dsi: &i2c_csi_dsi1 { }; // An alias for compatibility ++ ++csi0: &rp1_csi0 { }; ++csi1: &rp1_csi1 { }; ++dsi0: &rp1_dsi0 { }; ++dsi1: &rp1_dsi1 { }; ++dpi: &rp1_dpi { }; ++vec: &rp1_vec { }; ++dpi_gpio0: &rp1_dpi_24bit_gpio0 { }; ++dpi_gpio1: &rp1_dpi_24bit_gpio2 { }; ++dpi_18bit_cpadhi_gpio0: &rp1_dpi_18bit_cpadhi_gpio0 { }; ++dpi_18bit_cpadhi_gpio2: &rp1_dpi_18bit_cpadhi_gpio2 { }; ++dpi_18bit_gpio0: &rp1_dpi_18bit_gpio0 { }; ++dpi_18bit_gpio2: &rp1_dpi_18bit_gpio2 { }; ++dpi_16bit_cpadhi_gpio0: &rp1_dpi_16bit_cpadhi_gpio0 { }; ++dpi_16bit_cpadhi_gpio2: &rp1_dpi_16bit_cpadhi_gpio2 { }; ++dpi_16bit_gpio0: &rp1_dpi_16bit_gpio0 { }; ++dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; ++ ++/* Add the IOMMUs for some RP1 bus masters */ ++ ++&csi0 { ++ iommus = <&iommu5>; ++}; ++ ++&csi1 { ++ iommus = <&iommu5>; ++}; ++ ++&dsi0 { ++ iommus = <&iommu5>; ++}; ++ ++&dsi1 { ++ iommus = <&iommu5>; ++}; ++ ++&dpi { ++ iommus = <&iommu5>; ++}; ++ ++&vec { ++ iommus = <&iommu5>; ++}; ++ ++&ddc0 { ++ status = "disabled"; ++}; ++ ++&ddc1 { ++ status = "disabled"; ++}; ++ ++&hdmi0 { ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>; ++ clock-names = "hdmi", "bvb", "audio", "cec"; ++ status = "disabled"; ++}; ++ ++&hdmi1 { ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; ++ clock-names = "hdmi", "bvb", "audio", "cec"; ++ status = "disabled"; ++}; ++ ++&hvs { ++ clocks = <&firmware_clocks 4>, <&firmware_clocks 16>; ++ clock-names = "core", "disp"; ++}; ++ ++&mop { ++ status = "disabled"; ++}; ++ ++&moplet { ++ status = "disabled"; ++}; ++ ++&pixelvalve0 { ++ status = "disabled"; ++}; ++ ++&pixelvalve1 { ++ status = "disabled"; ++}; ++ ++&disp_intr { ++ status = "disabled"; ++}; ++ ++/* SDIO1 is used to drive the SD card */ ++&sdio1 { ++ pinctrl-0 = <&emmc_sd_pulls>, <&emmc_aon_cd_pins>; ++ pinctrl-names = "default"; ++ vqmmc-supply = <&sd_io_1v8_reg>; ++ vmmc-supply = <&sd_vcc_reg>; ++ bus-width = <4>; ++ sd-uhs-sdr50; ++ sd-uhs-ddr50; ++ sd-uhs-sdr104; ++ cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>; ++ //no-1-8-v; ++ status = "okay"; ++}; ++ ++&pinctrl_aon { ++ emmc_aon_cd_pins: emmc_aon_cd_pins { ++ function = "sd_card_g"; ++ pins = "aon_gpio5"; ++ bias-pull-up; ++ }; ++ ++ /* Slight hack - only one PWM pin (status LED) is usable */ ++ aon_pwm_1pin: aon_pwm_1pin { ++ function = "aon_pwm"; ++ pins = "aon_gpio9"; ++ }; ++}; ++ ++&pinctrl { ++ pwr_button_pins: pwr_button_pins { ++ function = "gpio"; ++ pins = "gpio20"; ++ bias-pull-up; ++ }; ++ ++ wl_on_pins: wl_on_pins { ++ function = "gpio"; ++ pins = "gpio28"; ++ }; ++ ++ bt_shutdown_pins: bt_shutdown_pins { ++ function = "gpio"; ++ pins = "gpio29"; ++ }; ++ ++ emmc_sd_pulls: emmc_sd_pulls { ++ pins = "emmc_cmd", "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3"; ++ bias-pull-up; ++ }; ++}; ++ ++/* uarta communicates with the BT module */ ++&uarta { ++ uart-has-rtscts; ++ auto-flow-control; ++ status = "okay"; ++ clock-frequency = <96000000>; ++ pinctrl-0 = <&uarta_24_pins &bt_shutdown_pins>; ++ pinctrl-names = "default"; ++ ++ bluetooth: bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <3000000>; ++ shutdown-gpios = <&gio 29 GPIO_ACTIVE_HIGH>; ++ local-bd-address = [ 00 00 00 00 00 00 ]; ++ }; ++}; ++ ++&i2c_rp1boot { ++ clock-frequency = <400000>; ++ pinctrl-0 = <&i2c3_m4_agpio0_pins>; ++ pinctrl-names = "default"; ++}; ++ ++/ { ++ chosen: chosen { ++ bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe"; ++ stdout-path = "serial10:115200n8"; ++ }; ++ ++ fan: cooling_fan { ++ status = "disabled"; ++ compatible = "pwm-fan"; ++ #cooling-cells = <2>; ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ cooling-levels = <0 75 125 175 250>; ++ pwms = <&rp1_pwm1 3 41566 PWM_POLARITY_INVERTED>; ++ rpm-regmap = <&rp1_pwm1>; ++ rpm-offset = <0x3c>; ++ }; ++ ++ pwr_button { ++ compatible = "gpio-keys"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwr_button_pins>; ++ status = "okay"; ++ ++ pwr_key: pwr { ++ label = "pwr_button"; ++ // linux,code = <205>; // KEY_SUSPEND ++ linux,code = <116>; // KEY_POWER ++ gpios = <&gio 20 GPIO_ACTIVE_LOW>; ++ debounce-interval = <50>; // ms ++ }; ++ }; ++}; ++ ++&usb { ++ power-domains = <&power RPI_POWER_DOMAIN_USB>; ++}; ++ ++/* SDIO2 drives the WLAN interface */ ++&sdio2 { ++ pinctrl-0 = <&sdio2_30_pins>; ++ pinctrl-names = "default"; ++ bus-width = <4>; ++ vmmc-supply = <&wl_on_reg>; ++ sd-uhs-ddr50; ++ non-removable; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ wifi: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++}; ++ ++&rpivid { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ spi10_gpio2: spi10_gpio2 { ++ function = "vc_spi0"; ++ pins = "gpio2", "gpio3", "gpio4"; ++ bias-disable; ++ }; ++ ++ spi10_cs_gpio1: spi10_cs_gpio1 { ++ function = "gpio"; ++ pins = "gpio1"; ++ bias-pull-up; ++ }; ++}; ++ ++spi10_pins: &spi10_gpio2 {}; ++spi10_cs_pins: &spi10_cs_gpio1 {}; ++ ++&spi10 { ++ pinctrl-names = "default"; ++ cs-gpios = <&gio 1 1>; ++ pinctrl-0 = <&spi10_pins &spi10_cs_pins>; ++ ++ spidev10: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <20000000>; ++ status = "okay"; ++ }; ++}; ++ ++// ============================================= ++// Board specific stuff here ++ ++&gio_aon { ++ // Don't use GIO_AON as an interrupt controller because it will ++ // clash with the firmware monitoring the PMIC interrupt via the VPU. ++ ++ /delete-property/ interrupt-controller; ++}; ++ ++&main_aon_irq { ++ // Don't use the MAIN_AON_IRQ interrupt controller because it will ++ // clash with the firmware monitoring the PMIC interrupt via the VPU. ++ ++ status = "disabled"; ++}; ++ ++&rp1_pwm1 { ++ status = "disabled"; ++ pinctrl-0 = <&rp1_pwm1_gpio45>; ++ pinctrl-names = "default"; ++}; ++ ++&thermal_trips { ++ cpu_tepid: cpu-tepid { ++ temperature = <50000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_warm: cpu-warm { ++ temperature = <60000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_hot: cpu-hot { ++ temperature = <67500>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_vhot: cpu-vhot { ++ temperature = <75000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++}; ++ ++&cooling_maps { ++ tepid { ++ trip = <&cpu_tepid>; ++ cooling-device = <&fan 1 1>; ++ }; ++ ++ warm { ++ trip = <&cpu_warm>; ++ cooling-device = <&fan 2 2>; ++ }; ++ ++ hot { ++ trip = <&cpu_hot>; ++ cooling-device = <&fan 3 3>; ++ }; ++ ++ vhot { ++ trip = <&cpu_vhot>; ++ cooling-device = <&fan 4 4>; ++ }; ++ ++ melt { ++ trip = <&cpu_crit>; ++ cooling-device = <&fan 4 4>; ++ }; ++}; ++ ++&gio { ++ // The GPIOs above 35 are not used on Pi 5, so shrink the upper bank ++ // to reduce the clutter in gpioinfo/pinctrl ++ brcm,gpio-bank-widths = <32 4>; ++ ++ gpio-line-names = ++ "-", // GPIO_000 ++ "2712_BOOT_CS_N", // GPIO_001 ++ "2712_BOOT_MISO", // GPIO_002 ++ "2712_BOOT_MOSI", // GPIO_003 ++ "2712_BOOT_SCLK", // GPIO_004 ++ "-", // GPIO_005 ++ "-", // GPIO_006 ++ "-", // GPIO_007 ++ "-", // GPIO_008 ++ "-", // GPIO_009 ++ "-", // GPIO_010 ++ "-", // GPIO_011 ++ "-", // GPIO_012 ++ "-", // GPIO_013 ++ "PCIE_SDA", // GPIO_014 ++ "PCIE_SCL", // GPIO_015 ++ "-", // GPIO_016 ++ "-", // GPIO_017 ++ "-", // GPIO_018 ++ "-", // GPIO_019 ++ "PWR_GPIO", // GPIO_020 ++ "2712_G21_FS", // GPIO_021 ++ "-", // GPIO_022 ++ "-", // GPIO_023 ++ "BT_RTS", // GPIO_024 ++ "BT_CTS", // GPIO_025 ++ "BT_TXD", // GPIO_026 ++ "BT_RXD", // GPIO_027 ++ "WL_ON", // GPIO_028 ++ "BT_ON", // GPIO_029 ++ "WIFI_SDIO_CLK", // GPIO_030 ++ "WIFI_SDIO_CMD", // GPIO_031 ++ "WIFI_SDIO_D0", // GPIO_032 ++ "WIFI_SDIO_D1", // GPIO_033 ++ "WIFI_SDIO_D2", // GPIO_034 ++ "WIFI_SDIO_D3"; // GPIO_035 ++}; ++ ++&gio_aon { ++ gpio-line-names = ++ "RP1_SDA", // AON_GPIO_00 ++ "RP1_SCL", // AON_GPIO_01 ++ "RP1_RUN", // AON_GPIO_02 ++ "SD_IOVDD_SEL", // AON_GPIO_03 ++ "SD_PWR_ON", // AON_GPIO_04 ++ "SD_CDET_N", // AON_GPIO_05 ++ "SD_FLG_N", // AON_GPIO_06 ++ "-", // AON_GPIO_07 ++ "2712_WAKE", // AON_GPIO_08 ++ "2712_STAT_LED", // AON_GPIO_09 ++ "-", // AON_GPIO_10 ++ "-", // AON_GPIO_11 ++ "PMIC_INT", // AON_GPIO_12 ++ "UART_TX_FS", // AON_GPIO_13 ++ "UART_RX_FS", // AON_GPIO_14 ++ "-", // AON_GPIO_15 ++ "-", // AON_GPIO_16 ++ ++ // Pad bank0 out to 32 entries ++ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ++ ++ "HDMI0_SCL", // AON_SGPIO_00 ++ "HDMI0_SDA", // AON_SGPIO_01 ++ "HDMI1_SCL", // AON_SGPIO_02 ++ "HDMI1_SDA", // AON_SGPIO_03 ++ "PMIC_SCL", // AON_SGPIO_04 ++ "PMIC_SDA"; // AON_SGPIO_05 ++ ++ rp1_run_hog { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RP1 RUN pin"; ++ }; ++}; ++ ++&rp1_gpio { ++ gpio-line-names = ++ "ID_SDA", // GPIO0 ++ "ID_SCL", // GPIO1 ++ "GPIO2", // GPIO2 ++ "GPIO3", // GPIO3 ++ "GPIO4", // GPIO4 ++ "GPIO5", // GPIO5 ++ "GPIO6", // GPIO6 ++ "GPIO7", // GPIO7 ++ "GPIO8", // GPIO8 ++ "GPIO9", // GPIO9 ++ "GPIO10", // GPIO10 ++ "GPIO11", // GPIO11 ++ "GPIO12", // GPIO12 ++ "GPIO13", // GPIO13 ++ "GPIO14", // GPIO14 ++ "GPIO15", // GPIO15 ++ "GPIO16", // GPIO16 ++ "GPIO17", // GPIO17 ++ "GPIO18", // GPIO18 ++ "GPIO19", // GPIO19 ++ "GPIO20", // GPIO20 ++ "GPIO21", // GPIO21 ++ "GPIO22", // GPIO22 ++ "GPIO23", // GPIO23 ++ "GPIO24", // GPIO24 ++ "GPIO25", // GPIO25 ++ "GPIO26", // GPIO26 ++ "GPIO27", // GPIO27 ++ ++ "PCIE_RP1_WAKE", // GPIO28 ++ "FAN_TACH", // GPIO29 ++ "HOST_SDA", // GPIO30 ++ "HOST_SCL", // GPIO31 ++ "ETH_RST_N", // GPIO32 ++ "-", // GPIO33 ++ ++ "CD0_IO0_MICCLK", // GPIO34 ++ "CD0_IO0_MICDAT0", // GPIO35 ++ "RP1_PCIE_CLKREQ_N", // GPIO36 ++ "-", // GPIO37 ++ "CD0_SDA", // GPIO38 ++ "CD0_SCL", // GPIO39 ++ "CD1_SDA", // GPIO40 ++ "CD1_SCL", // GPIO41 ++ "USB_VBUS_EN", // GPIO42 ++ "USB_OC_N", // GPIO43 ++ "RP1_STAT_LED", // GPIO44 ++ "FAN_PWM", // GPIO45 ++ "CD1_IO0_MICCLK", // GPIO46 ++ "2712_WAKE", // GPIO47 ++ "CD1_IO1_MICDAT1", // GPIO48 ++ "EN_MAX_USB_CUR", // GPIO49 ++ "-", // GPIO50 ++ "-", // GPIO51 ++ "-", // GPIO52 ++ "-"; // GPIO53 ++ ++ usb_vbus_pins: usb_vbus_pins { ++ function = "vbus1"; ++ pins = "gpio42", "gpio43"; ++ }; ++}; ++ ++/ { ++ aliases: aliases { ++ blconfig = &blconfig; ++ blpubkey = &blpubkey; ++ bluetooth = &bluetooth; ++ console = &uart10; ++ ethernet0 = &rp1_eth; ++ wifi0 = &wifi; ++ fb = &fb; ++ mailbox = &mailbox; ++ mmc0 = &sdio1; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ uart2 = &uart2; ++ uart3 = &uart3; ++ uart4 = &uart4; ++ uart10 = &uart10; ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ serial10 = &uart10; ++ i2c = &i2c_arm; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ i2c6 = &i2c6; ++ i2c10 = &i2c_rp1boot; ++ // Bit-bashed i2c_gpios start at 10 ++ spi0 = &spi0; ++ spi1 = &spi1; ++ spi2 = &spi2; ++ spi3 = &spi3; ++ spi4 = &spi4; ++ spi5 = &spi5; ++ spi10 = &spi10; ++ gpio0 = &gpio; ++ gpio1 = &gio; ++ gpio2 = &gio_aon; ++ gpio3 = &pinctrl; ++ gpio4 = &pinctrl_aon; ++ usb0 = &rp1_usb0; ++ usb1 = &rp1_usb1; ++ drm-dsi1 = &dsi0; ++ drm-dsi2 = &dsi1; ++ }; ++ ++ __overrides__ { ++ bdaddr = <&bluetooth>, "local-bd-address["; ++ button_debounce = <&pwr_key>, "debounce-interval:0"; ++ cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status"; ++ uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0; ++ i2c0 = <&i2c0>, "status"; ++ i2c1 = <&i2c1>, "status"; ++ i2c = <&i2c1>, "status"; ++ i2c_arm = <&i2c_arm>, "status"; ++ i2c_vc = <&i2c_vc>, "status"; ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status"; ++ i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status"; ++ i2c0_baudrate = <&i2c0>, "clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>, "clock-frequency:0"; ++ i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; ++ i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; ++ i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; ++ krnbt = <&bluetooth>, "status"; ++ nvme = <&pciex1>, "status"; ++ pciex1 = <&pciex1>, "status"; ++ pciex1_gen = <&pciex1> , "max-link-speed:0"; ++ pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; ++ pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; ++ pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; ++ random = <&random>, "status"; ++ rtc = <&rpi_rtc>, "status"; ++ rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; ++ sd_cqe = <&sdio1>, "supports-cqe?"; ++ spi = <&spi0>, "status"; ++ suspend = <&pwr_key>, "linux,code:0=205"; ++ uart0 = <&uart0>, "status"; ++ wifiaddr = <&wifi>, "local-mac-address["; ++ ++ act_led_gpio = <&led_act>,"gpios:4",<&led_act>,"gpios:0=",<&gpio>; ++ act_led_activelow = <&led_act>,"gpios:8"; ++ act_led_trigger = <&led_act>, "linux,default-trigger"; ++ pwr_led_gpio = <&led_pwr>,"gpios:4"; ++ pwr_led_activelow = <&led_pwr>, "gpios:8"; ++ pwr_led_trigger = <&led_pwr>, "linux,default-trigger"; ++ eth_led0 = <&phy1>,"led-modes:0"; ++ eth_led1 = <&phy1>,"led-modes:4"; ++ drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; ++ drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; ++ drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; ++ drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; ++ drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0; ++ drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1; ++ drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi; ++ drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; ++ drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0; ++ drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; ++ drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; ++ drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; ++ ++ fan_temp0 = <&cpu_tepid>,"temperature:0"; ++ fan_temp1 = <&cpu_warm>,"temperature:0"; ++ fan_temp2 = <&cpu_hot>,"temperature:0"; ++ fan_temp3 = <&cpu_vhot>,"temperature:0"; ++ fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0"; ++ fan_temp1_hyst = <&cpu_warm>,"hysteresis:0"; ++ fan_temp2_hyst = <&cpu_hot>,"hysteresis:0"; ++ fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0"; ++ fan_temp0_speed = <&fan>, "cooling-levels:4"; ++ fan_temp1_speed = <&fan>, "cooling-levels:8"; ++ fan_temp2_speed = <&fan>, "cooling-levels:12"; ++ fan_temp3_speed = <&fan>, "cooling-levels:16"; ++ }; ++}; +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5-cm4io.dts ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5-cm4io.dts +@@ -1,2 +1,20 @@ + // SPDX-License-Identifier: GPL-2.0 +-#include "arm/broadcom/bcm2712-rpi-cm5-cm4io.dts" ++/dts-v1/; ++ ++#include "bcm2712-rpi-cm5.dtsi" ++ ++// The RP1 USB3 interfaces are not usable on CM4IO ++ ++&rp1_usb0 { ++ status = "disabled"; ++}; ++ ++&rp1_usb1 { ++ status = "disabled"; ++}; ++ ++/ { ++ __overrides__ { ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ }; ++}; +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5-cm5io.dts ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5-cm5io.dts +@@ -1,2 +1,10 @@ + // SPDX-License-Identifier: GPL-2.0 +-#include "arm/broadcom/bcm2712-rpi-cm5-cm5io.dts" ++/dts-v1/; ++ ++#include "bcm2712-rpi-cm5.dtsi" ++ ++/ { ++ __overrides__ { ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi ++++ /dev/null +@@ -1,890 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define i2c0 _i2c0 +-#define i2c3 _i2c3 +-#define i2c4 _i2c4 +-#define i2c5 _i2c5 +-#define i2c6 _i2c6 +-#define i2c8 _i2c8 +-#define i2s _i2s +-#define pwm0 _pwm0 +-#define pwm1 _pwm1 +-#define spi0 _spi0 +-#define spi3 _spi3 +-#define spi4 _spi4 +-#define spi5 _spi5 +-#define spi6 _spi6 +-#define uart0 _uart0 +-#define uart2 _uart2 +-#define uart5 _uart5 +- +-#include "bcm2712.dtsi" +- +-#undef i2c0 +-#undef i2c3 +-#undef i2c4 +-#undef i2c5 +-#undef i2c6 +-#undef i2c8 +-#undef i2s +-#undef pwm0 +-#undef pwm1 +-#undef spi0 +-#undef spi3 +-#undef spi4 +-#undef spi5 +-#undef spi6 +-#undef uart0 +-#undef uart2 +-#undef uart3 +-#undef uart4 +-#undef uart5 +- +-/ { +- compatible = "raspberrypi,5-compute-module", "brcm,bcm2712"; +- model = "Raspberry Pi Compute Module 5"; +- +- /* Will be filled by the bootloader */ +- memory@0 { +- device_type = "memory"; +- reg = <0 0 0x28000000>; +- }; +- +- leds: leds { +- compatible = "gpio-leds"; +- +- led_pwr: led-pwr { +- label = "PWR"; +- gpios = <&rp1_gpio 44 GPIO_ACTIVE_LOW>; +- default-state = "off"; +- linux,default-trigger = "none"; +- }; +- +- led_act: led-act { +- label = "ACT"; +- gpios = <&gio_aon 9 GPIO_ACTIVE_LOW>; +- default-state = "off"; +- linux,default-trigger = "mmc0"; +- }; +- }; +- +- sd_io_1v8_reg: sd_io_1v8_reg { +- compatible = "regulator-gpio"; +- regulator-name = "vdd-sd-io"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <3300000>; +- regulator-boot-on; +- regulator-always-on; +- regulator-settling-time-us = <5000>; +- gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>; +- states = <1800000 0x1 +- 3300000 0x0>; +- status = "okay"; +- }; +- +- sd_vcc_reg: sd_vcc_reg { +- compatible = "regulator-fixed"; +- regulator-name = "vcc-sd"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-boot-on; +- enable-active-high; +- gpios = <&gio_aon 4 GPIO_ACTIVE_HIGH>; +- status = "okay"; +- }; +- +- wl_on_reg: wl_on_reg { +- compatible = "regulator-fixed"; +- regulator-name = "wl-on-regulator"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- pinctrl-0 = <&wl_on_pins>; +- pinctrl-names = "default"; +- +- gpio = <&gio 28 GPIO_ACTIVE_HIGH>; +- +- startup-delay-us = <150000>; +- enable-active-high; +- }; +- +- clocks: clocks { +- }; +- +- cam1_clk: cam1_clk { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- status = "disabled"; +- }; +- +- cam0_clk: cam0_clk { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- status = "disabled"; +- }; +- +- cam0_reg: cam0_reg { +- compatible = "regulator-fixed"; +- regulator-name = "cam0_reg"; +- enable-active-high; +- status = "okay"; +- gpio = <&rp1_gpio 34 0>; // CD0_IO0_MICCLK, to CAM_GPIO on connector +- }; +- +- cam_dummy_reg: cam_dummy_reg { +- compatible = "regulator-fixed"; +- regulator-name = "cam-dummy-reg"; +- status = "okay"; +- }; +- +- dummy: dummy { +- // A target for unwanted overlay fragments +- }; +- +- +- // A few extra labels to keep overlays happy +- +- i2c0if: i2c0if {}; +- i2c0mux: i2c0mux {}; +-}; +- +-rp1_target: &pcie2 { +- brcm,enable-mps-rcb; +- brcm,vdm-qos-map = <0xbbaa9888>; +- aspm-no-l0s; +- status = "okay"; +-}; +- +-// Add some labels to 2712 device +- +-// The system UART +-uart10: &_uart0 { status = "okay"; }; +- +-// The system SPI for the bootloader EEPROM +-spi10: &_spi0 { status = "okay"; }; +- +-i2c_rp1boot: &_i2c3 { }; +- +-#include "rp1.dtsi" +- +-&rp1 { +- // PCIe address space layout: +- // 00_00000000-00_00xxxxxx = RP1 peripherals +- // 10_00000000-1x_xxxxxxxx = up to 64GB system RAM +- +- // outbound access aimed at PCIe 0_00xxxxxx -> RP1 c0_40xxxxxx +- // This is the RP1 peripheral space +- ranges = <0xc0 0x40000000 +- 0x02000000 0x00 0x00000000 +- 0x00 0x00400000>; +- +- dma-ranges = +- // inbound RP1 1x_xxxxxxxx -> PCIe 1x_xxxxxxxx +- <0x10 0x00000000 +- 0x43000000 0x10 0x00000000 +- 0x10 0x00000000>, +- +- // inbound RP1 c0_40xxxxxx -> PCIe 00_00xxxxxx +- // This allows the RP1 DMA controller to address RP1 hardware +- <0xc0 0x40000000 +- 0x02000000 0x0 0x00000000 +- 0x0 0x00400000>, +- +- // inbound RP1 0x_xxxxxxxx -> PCIe 1x_xxxxxxxx +- <0x00 0x00000000 +- 0x02000000 0x10 0x00000000 +- 0x10 0x00000000>; +-}; +- +-// Expose RP1 nodes as system nodes with labels +- +-&rp1_dma { +- status = "okay"; +-}; +- +-&rp1_eth { +- status = "okay"; +- phy-handle = <&phy1>; +- phy-reset-gpios = <&rp1_gpio 32 GPIO_ACTIVE_LOW>; +- phy-reset-duration = <5>; +- +- phy1: ethernet-phy@1 { +- reg = <0x1>; +- brcm,powerdown-enable; +- interrupt-parent = <&gpio>; +- interrupts = <37 IRQ_TYPE_LEVEL_LOW>; +- }; +-}; +- +-gpio: &rp1_gpio { +- status = "okay"; +-}; +- +-aux: &dummy {}; +- +-&rp1_usb0 { +- pinctrl-0 = <&usb_vbus_pins>; +- pinctrl-names = "default"; +- status = "okay"; +-}; +- +-&rp1_usb1 { +- status = "okay"; +-}; +- +-#include "bcm2712-rpi.dtsi" +- +-i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only +- pinctrl-0 = <&rp1_i2c6_38_39>; +- pinctrl-names = "default"; +- clock-frequency = <100000>; +-}; +- +-i2c_csi_dsi1: &i2c0 { // Note: This is for MIPI1 connector +-}; +- +-i2c_csi_dsi: &i2c_csi_dsi1 { }; // An alias for compatibility +- +-cam1_reg: &cam0_reg { // Shares CAM_GPIO with cam0_reg +-}; +- +-csi0: &rp1_csi0 { }; +-csi1: &rp1_csi1 { }; +-dsi0: &rp1_dsi0 { }; +-dsi1: &rp1_dsi1 { }; +-dpi: &rp1_dpi { }; +-vec: &rp1_vec { }; +-dpi_gpio0: &rp1_dpi_24bit_gpio0 { }; +-dpi_gpio1: &rp1_dpi_24bit_gpio2 { }; +-dpi_18bit_cpadhi_gpio0: &rp1_dpi_18bit_cpadhi_gpio0 { }; +-dpi_18bit_cpadhi_gpio2: &rp1_dpi_18bit_cpadhi_gpio2 { }; +-dpi_18bit_gpio0: &rp1_dpi_18bit_gpio0 { }; +-dpi_18bit_gpio2: &rp1_dpi_18bit_gpio2 { }; +-dpi_16bit_cpadhi_gpio0: &rp1_dpi_16bit_cpadhi_gpio0 { }; +-dpi_16bit_cpadhi_gpio2: &rp1_dpi_16bit_cpadhi_gpio2 { }; +-dpi_16bit_gpio0: &rp1_dpi_16bit_gpio0 { }; +-dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; +- +-/* Add the IOMMUs for some RP1 bus masters */ +- +-&csi0 { +- iommus = <&iommu5>; +-}; +- +-&csi1 { +- iommus = <&iommu5>; +-}; +- +-&dsi0 { +- iommus = <&iommu5>; +-}; +- +-&dsi1 { +- iommus = <&iommu5>; +-}; +- +-&dpi { +- iommus = <&iommu5>; +-}; +- +-&vec { +- iommus = <&iommu5>; +-}; +- +-&ddc0 { +- status = "disabled"; +-}; +- +-&ddc1 { +- status = "disabled"; +-}; +- +-&hdmi0 { +- clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>; +- clock-names = "hdmi", "bvb", "audio", "cec"; +- status = "disabled"; +-}; +- +-&hdmi1 { +- clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; +- clock-names = "hdmi", "bvb", "audio", "cec"; +- status = "disabled"; +-}; +- +-&hvs { +- clocks = <&firmware_clocks 4>, <&firmware_clocks 16>; +- clock-names = "core", "disp"; +-}; +- +-&mop { +- status = "disabled"; +-}; +- +-&moplet { +- status = "disabled"; +-}; +- +-&pixelvalve0 { +- status = "disabled"; +-}; +- +-&pixelvalve1 { +- status = "disabled"; +-}; +- +-&disp_intr { +- status = "disabled"; +-}; +- +-/* SDIO1 is used to drive the eMMC/SD card */ +-&sdio1 { +- pinctrl-0 = <&emmc_cmddat_pulls>, <&emmc_ds_pull>; +- pinctrl-names = "default"; +- vqmmc-supply = <&sd_io_1v8_reg>; +- vmmc-supply = <&sd_vcc_reg>; +- bus-width = <8>; +- sd-uhs-sdr50; +- sd-uhs-ddr50; +- sd-uhs-sdr104; +- mmc-hs200-1_8v; +- mmc-hs400-1_8v; +- mmc-hs400-enhanced-strobe; +- broken-cd; +- supports-cqe; +- status = "okay"; +-}; +- +-&pinctrl_aon { +- ant_pins: ant_pins { +- function = "gpio"; +- pins = "aon_gpio5", "aon_gpio6"; +- }; +- +- /* Slight hack - only one PWM pin (status LED) is usable */ +- aon_pwm_1pin: aon_pwm_1pin { +- function = "aon_pwm"; +- pins = "aon_gpio9"; +- }; +-}; +- +-&pinctrl { +- pwr_button_pins: pwr_button_pins { +- function = "gpio"; +- pins = "gpio20"; +- bias-pull-up; +- }; +- +- wl_on_pins: wl_on_pins { +- function = "gpio"; +- pins = "gpio28"; +- }; +- +- bt_shutdown_pins: bt_shutdown_pins { +- function = "gpio"; +- pins = "gpio29"; +- }; +- +- emmc_ds_pull: emmc_ds_pull { +- pins = "emmc_ds"; +- bias-pull-down; +- }; +- +- emmc_cmddat_pulls: emmc_cmddat_pulls { +- pins = "emmc_cmd", "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3", +- "emmc_dat4", "emmc_dat5", "emmc_dat6", "emmc_dat7"; +- bias-pull-up; +- }; +-}; +- +-/* uarta communicates with the BT module */ +-&uarta { +- uart-has-rtscts; +- auto-flow-control; +- status = "okay"; +- clock-frequency = <96000000>; +- pinctrl-0 = <&uarta_24_pins &bt_shutdown_pins>; +- pinctrl-names = "default"; +- +- bluetooth: bluetooth { +- compatible = "brcm,bcm43438-bt"; +- max-speed = <3000000>; +- shutdown-gpios = <&gio 29 GPIO_ACTIVE_HIGH>; +- local-bd-address = [ 00 00 00 00 00 00 ]; +- }; +-}; +- +-&i2c_rp1boot { +- clock-frequency = <400000>; +- pinctrl-0 = <&i2c3_m4_agpio0_pins>; +- pinctrl-names = "default"; +-}; +- +-/ { +- chosen: chosen { +- bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe"; +- stdout-path = "serial10:115200n8"; +- }; +- +- fan: cooling_fan { +- status = "disabled"; +- compatible = "pwm-fan"; +- #cooling-cells = <2>; +- cooling-min-state = <0>; +- cooling-max-state = <3>; +- cooling-levels = <0 75 125 175 250>; +- pwms = <&rp1_pwm1 3 41566 PWM_POLARITY_INVERTED>; +- rpm-regmap = <&rp1_pwm1>; +- rpm-offset = <0x3c>; +- }; +- +- pwr_button { +- compatible = "gpio-keys"; +- +- pinctrl-names = "default"; +- pinctrl-0 = <&pwr_button_pins>; +- status = "okay"; +- +- pwr_key: pwr { +- label = "pwr_button"; +- // linux,code = <205>; // KEY_SUSPEND +- linux,code = <116>; // KEY_POWER +- gpios = <&gio 20 GPIO_ACTIVE_LOW>; +- debounce-interval = <50>; // ms +- }; +- }; +-}; +- +-&usb { +- power-domains = <&power RPI_POWER_DOMAIN_USB>; +-}; +- +-/* SDIO2 drives the WLAN interface */ +-&sdio2 { +- pinctrl-0 = <&sdio2_30_pins>, <&ant_pins>; +- pinctrl-names = "default"; +- bus-width = <4>; +- vmmc-supply = <&wl_on_reg>; +- sd-uhs-ddr50; +- non-removable; +- status = "okay"; +- #address-cells = <1>; +- #size-cells = <0>; +- +- wifi: wifi@1 { +- reg = <1>; +- compatible = "brcm,bcm4329-fmac"; +- local-mac-address = [00 00 00 00 00 00]; +- }; +-}; +- +-&rpivid { +- status = "okay"; +-}; +- +-&pinctrl { +- spi10_gpio2: spi10_gpio2 { +- function = "vc_spi0"; +- pins = "gpio2", "gpio3", "gpio4"; +- bias-disable; +- }; +- +- spi10_cs_gpio1: spi10_cs_gpio1 { +- function = "gpio"; +- pins = "gpio1"; +- bias-pull-up; +- }; +-}; +- +-spi10_pins: &spi10_gpio2 {}; +-spi10_cs_pins: &spi10_cs_gpio1 {}; +- +-&spi10 { +- pinctrl-names = "default"; +- cs-gpios = <&gio 1 1>; +- pinctrl-0 = <&spi10_pins &spi10_cs_pins>; +- +- spidev10: spidev@0 { +- compatible = "spidev"; +- reg = <0>; /* CE0 */ +- #address-cells = <1>; +- #size-cells = <0>; +- spi-max-frequency = <20000000>; +- status = "okay"; +- }; +-}; +- +-// ============================================= +-// Board specific stuff here +- +-&gio_aon { +- // Don't use GIO_AON as an interrupt controller because it will +- // clash with the firmware monitoring the PMIC interrupt via the VPU. +- +- /delete-property/ interrupt-controller; +-}; +- +-&main_aon_irq { +- // Don't use the MAIN_AON_IRQ interrupt controller because it will +- // clash with the firmware monitoring the PMIC interrupt via the VPU. +- +- status = "disabled"; +-}; +- +-&rp1_pwm1 { +- status = "disabled"; +- pinctrl-0 = <&rp1_pwm1_gpio45>; +- pinctrl-names = "default"; +-}; +- +-&thermal_trips { +- cpu_tepid: cpu-tepid { +- temperature = <50000>; +- hysteresis = <5000>; +- type = "active"; +- }; +- +- cpu_warm: cpu-warm { +- temperature = <60000>; +- hysteresis = <5000>; +- type = "active"; +- }; +- +- cpu_hot: cpu-hot { +- temperature = <67500>; +- hysteresis = <5000>; +- type = "active"; +- }; +- +- cpu_vhot: cpu-vhot { +- temperature = <75000>; +- hysteresis = <5000>; +- type = "active"; +- }; +-}; +- +-&cooling_maps { +- tepid { +- trip = <&cpu_tepid>; +- cooling-device = <&fan 1 1>; +- }; +- +- warm { +- trip = <&cpu_warm>; +- cooling-device = <&fan 2 2>; +- }; +- +- hot { +- trip = <&cpu_hot>; +- cooling-device = <&fan 3 3>; +- }; +- +- vhot { +- trip = <&cpu_vhot>; +- cooling-device = <&fan 4 4>; +- }; +- +- melt { +- trip = <&cpu_crit>; +- cooling-device = <&fan 4 4>; +- }; +-}; +- +-&gio { +- // The GPIOs above 35 are not used on Pi 5, so shrink the upper bank +- // to reduce the clutter in gpioinfo/pinctrl +- brcm,gpio-bank-widths = <32 4>; +- +- gpio-line-names = +- "-", // GPIO_000 +- "2712_BOOT_CS_N", // GPIO_001 +- "2712_BOOT_MISO", // GPIO_002 +- "2712_BOOT_MOSI", // GPIO_003 +- "2712_BOOT_SCLK", // GPIO_004 +- "-", // GPIO_005 +- "-", // GPIO_006 +- "-", // GPIO_007 +- "-", // GPIO_008 +- "-", // GPIO_009 +- "-", // GPIO_010 +- "-", // GPIO_011 +- "-", // GPIO_012 +- "-", // GPIO_013 +- "-", // GPIO_014 +- "-", // GPIO_015 +- "-", // GPIO_016 +- "-", // GPIO_017 +- "-", // GPIO_018 +- "-", // GPIO_019 +- "PWR_GPIO", // GPIO_020 +- "2712_G21_FS", // GPIO_021 +- "-", // GPIO_022 +- "-", // GPIO_023 +- "BT_RTS", // GPIO_024 +- "BT_CTS", // GPIO_025 +- "BT_TXD", // GPIO_026 +- "BT_RXD", // GPIO_027 +- "WL_ON", // GPIO_028 +- "BT_ON", // GPIO_029 +- "WIFI_SDIO_CLK", // GPIO_030 +- "WIFI_SDIO_CMD", // GPIO_031 +- "WIFI_SDIO_D0", // GPIO_032 +- "WIFI_SDIO_D1", // GPIO_033 +- "WIFI_SDIO_D2", // GPIO_034 +- "WIFI_SDIO_D3"; // GPIO_035 +-}; +- +-&gio_aon { +- gpio-line-names = +- "RP1_SDA", // AON_GPIO_00 +- "RP1_SCL", // AON_GPIO_01 +- "RP1_RUN", // AON_GPIO_02 +- "SD_IOVDD_SEL", // AON_GPIO_03 +- "SD_PWR_ON", // AON_GPIO_04 +- "ANT1", // AON_GPIO_05 +- "ANT2", // AON_GPIO_06 +- "-", // AON_GPIO_07 +- "2712_WAKE", // AON_GPIO_08 +- "2712_STAT_LED", // AON_GPIO_09 +- "-", // AON_GPIO_10 +- "-", // AON_GPIO_11 +- "PMIC_INT", // AON_GPIO_12 +- "UART_TX_FS", // AON_GPIO_13 +- "UART_RX_FS", // AON_GPIO_14 +- "-", // AON_GPIO_15 +- "-", // AON_GPIO_16 +- +- // Pad bank0 out to 32 entries +- "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", +- +- "HDMI0_SCL", // AON_SGPIO_00 +- "HDMI0_SDA", // AON_SGPIO_01 +- "HDMI1_SCL", // AON_SGPIO_02 +- "HDMI1_SDA", // AON_SGPIO_03 +- "PMIC_SCL", // AON_SGPIO_04 +- "PMIC_SDA"; // AON_SGPIO_05 +- +- rp1_run_hog { +- gpio-hog; +- gpios = <2 GPIO_ACTIVE_HIGH>; +- output-high; +- line-name = "RP1 RUN pin"; +- }; +- +- ant1: ant1-hog { +- gpio-hog; +- gpios = <5 GPIO_ACTIVE_HIGH>; +- /* internal antenna enabled */ +- output-high; +- line-name = "ant1"; +- }; +- +- ant2: ant2-hog { +- gpio-hog; +- gpios = <6 GPIO_ACTIVE_HIGH>; +- /* external antenna disabled */ +- output-low; +- line-name = "ant2"; +- }; +-}; +- +-&rp1_gpio { +- gpio-line-names = +- "ID_SDA", // GPIO0 +- "ID_SCL", // GPIO1 +- "GPIO2", // GPIO2 +- "GPIO3", // GPIO3 +- "GPIO4", // GPIO4 +- "GPIO5", // GPIO5 +- "GPIO6", // GPIO6 +- "GPIO7", // GPIO7 +- "GPIO8", // GPIO8 +- "GPIO9", // GPIO9 +- "GPIO10", // GPIO10 +- "GPIO11", // GPIO11 +- "GPIO12", // GPIO12 +- "GPIO13", // GPIO13 +- "GPIO14", // GPIO14 +- "GPIO15", // GPIO15 +- "GPIO16", // GPIO16 +- "GPIO17", // GPIO17 +- "GPIO18", // GPIO18 +- "GPIO19", // GPIO19 +- "GPIO20", // GPIO20 +- "GPIO21", // GPIO21 +- "GPIO22", // GPIO22 +- "GPIO23", // GPIO23 +- "GPIO24", // GPIO24 +- "GPIO25", // GPIO25 +- "GPIO26", // GPIO26 +- "GPIO27", // GPIO27 +- +- "PCIE_PWR_EN", // GPIO28 +- "FAN_TACH", // GPIO29 +- "HOST_SDA", // GPIO30 +- "HOST_SCL", // GPIO31 +- "ETH_RST_N", // GPIO32 +- "PCIE_DET_WAKE", // GPIO33 +- +- "CD0_IO0_MICCLK", // GPIO34 +- "CD0_IO0_MICDAT0", // GPIO35 +- "RP1_PCIE_CLKREQ_N", // GPIO36 +- "ETH_IRQ_N", // GPIO37 +- "SDA0", // GPIO38 +- "SCL0", // GPIO39 +- "-", // GPIO40 +- "-", // GPIO41 +- "USB_VBUS_EN", // GPIO42 +- "USB_OC_N", // GPIO43 +- "RP1_STAT_LED", // GPIO44 +- "FAN_PWM", // GPIO45 +- "-", // GPIO46 +- "2712_WAKE", // GPIO47 +- "-", // GPIO48 +- "-", // GPIO49 +- "-", // GPIO50 +- "-", // GPIO51 +- "-", // GPIO52 +- "-"; // GPIO53 +- +- usb_vbus_pins: usb_vbus_pins { +- function = "vbus1"; +- pins = "gpio42", "gpio43"; +- }; +-}; +- +-/ { +- aliases: aliases { +- blconfig = &blconfig; +- blpubkey = &blpubkey; +- bluetooth = &bluetooth; +- console = &uart10; +- ethernet0 = &rp1_eth; +- wifi0 = &wifi; +- fb = &fb; +- mailbox = &mailbox; +- mmc0 = &sdio1; +- uart0 = &uart0; +- uart1 = &uart1; +- uart2 = &uart2; +- uart3 = &uart3; +- uart4 = &uart4; +- uart10 = &uart10; +- serial0 = &uart0; +- serial1 = &uart1; +- serial2 = &uart2; +- serial3 = &uart3; +- serial4 = &uart4; +- serial10 = &uart10; +- i2c = &i2c_arm; +- i2c0 = &i2c0; +- i2c1 = &i2c1; +- i2c2 = &i2c2; +- i2c3 = &i2c3; +- i2c4 = &i2c4; +- i2c5 = &i2c5; +- i2c6 = &i2c6; +- i2c10 = &i2c_rp1boot; +- // Bit-bashed i2c_gpios start at 10 +- spi0 = &spi0; +- spi1 = &spi1; +- spi2 = &spi2; +- spi3 = &spi3; +- spi4 = &spi4; +- spi5 = &spi5; +- spi10 = &spi10; +- gpio0 = &gpio; +- gpio1 = &gio; +- gpio2 = &gio_aon; +- gpio3 = &pinctrl; +- gpio4 = &pinctrl_aon; +- usb0 = &rp1_usb0; +- usb1 = &rp1_usb1; +- drm-dsi1 = &dsi0; +- drm-dsi2 = &dsi1; +- }; +- +- __overrides__ { +- bdaddr = <&bluetooth>, "local-bd-address["; +- button_debounce = <&pwr_key>, "debounce-interval:0"; +- cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status"; +- uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0; +- i2c0 = <&i2c0>, "status"; +- i2c1 = <&i2c1>, "status"; +- i2c = <&i2c1>, "status"; +- i2c_arm = <&i2c_arm>, "status"; +- i2c_vc = <&i2c_vc>, "status"; +- i2c_csi_dsi = <&i2c_csi_dsi>, "status"; +- i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status"; +- i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status"; +- i2c0_baudrate = <&i2c0>, "clock-frequency:0"; +- i2c1_baudrate = <&i2c1>, "clock-frequency:0"; +- i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; +- i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; +- i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; +- krnbt = <&bluetooth>, "status"; +- nvme = <&pciex1>, "status"; +- pciex1 = <&pciex1>, "status"; +- pciex1_gen = <&pciex1> , "max-link-speed:0"; +- pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; +- pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; +- pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; +- random = <&random>, "status"; +- rtc = <&rpi_rtc>, "status"; +- rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; +- spi = <&spi0>, "status"; +- suspend = <&pwr_key>, "linux,code:0=205"; +- uart0 = <&uart0>, "status"; +- wifiaddr = <&wifi>, "local-mac-address["; +- +- act_led_activelow = <&led_act>, "active-low?"; +- act_led_trigger = <&led_act>, "linux,default-trigger"; +- pwr_led_activelow = <&led_pwr>, "gpios:8"; +- pwr_led_trigger = <&led_pwr>, "linux,default-trigger"; +- eth_led0 = <&phy1>,"led-modes:0"; +- eth_led1 = <&phy1>,"led-modes:4"; +- drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; +- drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; +- drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; +- drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; +- drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0; +- drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1; +- drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi; +- drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; +- drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0; +- drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; +- drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; +- drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; +- +- ant1 = <&ant1>,"output-high?=on", +- <&ant1>, "output-low?=off", +- <&ant2>, "output-high?=off", +- <&ant2>, "output-low?=on"; +- ant2 = <&ant1>,"output-high?=off", +- <&ant1>, "output-low?=on", +- <&ant2>, "output-high?=on", +- <&ant2>, "output-low?=off"; +- noant = <&ant1>,"output-high?=off", +- <&ant1>, "output-low?=on", +- <&ant2>, "output-high?=off", +- <&ant2>, "output-low?=on"; +- +- fan_temp0 = <&cpu_tepid>,"temperature:0"; +- fan_temp1 = <&cpu_warm>,"temperature:0"; +- fan_temp2 = <&cpu_hot>,"temperature:0"; +- fan_temp3 = <&cpu_vhot>,"temperature:0"; +- fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0"; +- fan_temp1_hyst = <&cpu_warm>,"hysteresis:0"; +- fan_temp2_hyst = <&cpu_hot>,"hysteresis:0"; +- fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0"; +- fan_temp0_speed = <&fan>, "cooling-levels:4"; +- fan_temp1_speed = <&fan>, "cooling-levels:8"; +- fan_temp2_speed = <&fan>, "cooling-levels:12"; +- fan_temp3_speed = <&fan>, "cooling-levels:16"; +- }; +-}; +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi +@@ -0,0 +1,884 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define i2c0 _i2c0 ++#define i2c3 _i2c3 ++#define i2c4 _i2c4 ++#define i2c5 _i2c5 ++#define i2c6 _i2c6 ++#define i2c8 _i2c8 ++#define i2s _i2s ++#define pwm0 _pwm0 ++#define pwm1 _pwm1 ++#define spi0 _spi0 ++#define spi3 _spi3 ++#define spi4 _spi4 ++#define spi5 _spi5 ++#define spi6 _spi6 ++#define uart0 _uart0 ++#define uart2 _uart2 ++#define uart5 _uart5 ++ ++#include "bcm2712.dtsi" ++ ++#undef i2c0 ++#undef i2c3 ++#undef i2c4 ++#undef i2c5 ++#undef i2c6 ++#undef i2c8 ++#undef i2s ++#undef pwm0 ++#undef pwm1 ++#undef spi0 ++#undef spi3 ++#undef spi4 ++#undef spi5 ++#undef spi6 ++#undef uart0 ++#undef uart2 ++#undef uart3 ++#undef uart4 ++#undef uart5 ++ ++/ { ++ compatible = "raspberrypi,5-compute-module", "brcm,bcm2712"; ++ model = "Raspberry Pi Compute Module 5"; ++ ++ /* Will be filled by the bootloader */ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0 0 0x28000000>; ++ }; ++ ++ leds: leds { ++ compatible = "gpio-leds"; ++ ++ led_pwr: led-pwr { ++ label = "PWR"; ++ gpios = <&rp1_gpio 44 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "none"; ++ }; ++ ++ led_act: led-act { ++ label = "ACT"; ++ gpios = <&gio_aon 9 GPIO_ACTIVE_LOW>; ++ default-state = "off"; ++ linux,default-trigger = "mmc0"; ++ }; ++ }; ++ ++ sd_io_1v8_reg: sd_io_1v8_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd-sd-io"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ }; ++ ++ sd_vcc_reg: sd_vcc_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-sd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ enable-active-high; ++ gpios = <&gio_aon 4 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ }; ++ ++ wl_on_reg: wl_on_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "wl-on-regulator"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ pinctrl-0 = <&wl_on_pins>; ++ pinctrl-names = "default"; ++ ++ gpio = <&gio 28 GPIO_ACTIVE_HIGH>; ++ ++ startup-delay-us = <150000>; ++ enable-active-high; ++ }; ++ ++ clocks: clocks { ++ }; ++ ++ cam1_clk: cam1_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ cam0_clk: cam0_clk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ cam0_reg: cam0_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam0_reg"; ++ enable-active-high; ++ status = "okay"; ++ gpio = <&rp1_gpio 34 0>; // CD0_IO0_MICCLK, to CAM_GPIO on connector ++ }; ++ ++ cam_dummy_reg: cam_dummy_reg { ++ compatible = "regulator-fixed"; ++ regulator-name = "cam-dummy-reg"; ++ status = "okay"; ++ }; ++ ++ dummy: dummy { ++ // A target for unwanted overlay fragments ++ }; ++ ++ ++ // A few extra labels to keep overlays happy ++ ++ i2c0if: i2c0if {}; ++ i2c0mux: i2c0mux {}; ++}; ++ ++rp1_target: &pcie2 { ++ brcm,enable-mps-rcb; ++ brcm,vdm-qos-map = <0xbbaa9888>; ++ aspm-no-l0s; ++ status = "okay"; ++}; ++ ++// Add some labels to 2712 device ++ ++// The system UART ++uart10: &_uart0 { status = "okay"; }; ++ ++// The system SPI for the bootloader EEPROM ++spi10: &_spi0 { status = "okay"; }; ++ ++i2c_rp1boot: &_i2c3 { }; ++ ++#include "rp1.dtsi" ++ ++&rp1 { ++ // PCIe address space layout: ++ // 00_00000000-00_00xxxxxx = RP1 peripherals ++ // 10_00000000-1x_xxxxxxxx = up to 64GB system RAM ++ ++ // outbound access aimed at PCIe 0_00xxxxxx -> RP1 c0_40xxxxxx ++ // This is the RP1 peripheral space ++ ranges = <0xc0 0x40000000 ++ 0x02000000 0x00 0x00000000 ++ 0x00 0x00400000>; ++ ++ dma-ranges = ++ // inbound RP1 1x_xxxxxxxx -> PCIe 1x_xxxxxxxx ++ <0x10 0x00000000 ++ 0x43000000 0x10 0x00000000 ++ 0x10 0x00000000>, ++ ++ // inbound RP1 c0_40xxxxxx -> PCIe 00_00xxxxxx ++ // This allows the RP1 DMA controller to address RP1 hardware ++ <0xc0 0x40000000 ++ 0x02000000 0x0 0x00000000 ++ 0x0 0x00400000>, ++ ++ // inbound RP1 0x_xxxxxxxx -> PCIe 1x_xxxxxxxx ++ <0x00 0x00000000 ++ 0x02000000 0x10 0x00000000 ++ 0x10 0x00000000>; ++}; ++ ++// Expose RP1 nodes as system nodes with labels ++ ++&rp1_dma { ++ status = "okay"; ++}; ++ ++&rp1_eth { ++ status = "okay"; ++ phy-handle = <&phy1>; ++ phy-reset-gpios = <&rp1_gpio 32 GPIO_ACTIVE_LOW>; ++ phy-reset-duration = <5>; ++ ++ phy1: ethernet-phy@1 { ++ reg = <0x1>; ++ brcm,powerdown-enable; ++ interrupt-parent = <&gpio>; ++ interrupts = <37 IRQ_TYPE_LEVEL_LOW>; ++ }; ++}; ++ ++gpio: &rp1_gpio { ++ status = "okay"; ++}; ++ ++aux: &dummy {}; ++ ++&rp1_usb0 { ++ pinctrl-0 = <&usb_vbus_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++}; ++ ++&rp1_usb1 { ++ status = "okay"; ++}; ++ ++#include "bcm2712-rpi.dtsi" ++ ++i2c_csi_dsi0: &i2c6 { // Note: This is for MIPI0 connector only ++ pinctrl-0 = <&rp1_i2c6_38_39>; ++ pinctrl-names = "default"; ++ clock-frequency = <100000>; ++}; ++ ++i2c_csi_dsi1: &i2c0 { // Note: This is for MIPI1 connector ++}; ++ ++i2c_csi_dsi: &i2c_csi_dsi1 { }; // An alias for compatibility ++ ++cam1_reg: &cam0_reg { // Shares CAM_GPIO with cam0_reg ++}; ++ ++csi0: &rp1_csi0 { }; ++csi1: &rp1_csi1 { }; ++dsi0: &rp1_dsi0 { }; ++dsi1: &rp1_dsi1 { }; ++dpi: &rp1_dpi { }; ++vec: &rp1_vec { }; ++dpi_gpio0: &rp1_dpi_24bit_gpio0 { }; ++dpi_gpio1: &rp1_dpi_24bit_gpio2 { }; ++dpi_18bit_cpadhi_gpio0: &rp1_dpi_18bit_cpadhi_gpio0 { }; ++dpi_18bit_cpadhi_gpio2: &rp1_dpi_18bit_cpadhi_gpio2 { }; ++dpi_18bit_gpio0: &rp1_dpi_18bit_gpio0 { }; ++dpi_18bit_gpio2: &rp1_dpi_18bit_gpio2 { }; ++dpi_16bit_cpadhi_gpio0: &rp1_dpi_16bit_cpadhi_gpio0 { }; ++dpi_16bit_cpadhi_gpio2: &rp1_dpi_16bit_cpadhi_gpio2 { }; ++dpi_16bit_gpio0: &rp1_dpi_16bit_gpio0 { }; ++dpi_16bit_gpio2: &rp1_dpi_16bit_gpio2 { }; ++ ++/* Add the IOMMUs for some RP1 bus masters */ ++ ++&csi0 { ++ iommus = <&iommu5>; ++}; ++ ++&csi1 { ++ iommus = <&iommu5>; ++}; ++ ++&dsi0 { ++ iommus = <&iommu5>; ++}; ++ ++&dsi1 { ++ iommus = <&iommu5>; ++}; ++ ++&dpi { ++ iommus = <&iommu5>; ++}; ++ ++&vec { ++ iommus = <&iommu5>; ++}; ++ ++&ddc0 { ++ status = "disabled"; ++}; ++ ++&ddc1 { ++ status = "disabled"; ++}; ++ ++&hdmi0 { ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 0>, <&clk_27MHz>; ++ clock-names = "hdmi", "bvb", "audio", "cec"; ++ status = "disabled"; ++}; ++ ++&hdmi1 { ++ clocks = <&firmware_clocks 13>, <&firmware_clocks 14>, <&dvp 1>, <&clk_27MHz>; ++ clock-names = "hdmi", "bvb", "audio", "cec"; ++ status = "disabled"; ++}; ++ ++&hvs { ++ clocks = <&firmware_clocks 4>, <&firmware_clocks 16>; ++ clock-names = "core", "disp"; ++}; ++ ++&mop { ++ status = "disabled"; ++}; ++ ++&moplet { ++ status = "disabled"; ++}; ++ ++&pixelvalve0 { ++ status = "disabled"; ++}; ++ ++&pixelvalve1 { ++ status = "disabled"; ++}; ++ ++&disp_intr { ++ status = "disabled"; ++}; ++ ++/* SDIO1 is used to drive the eMMC/SD card */ ++&sdio1 { ++ pinctrl-0 = <&emmc_cmddat_pulls>, <&emmc_ds_pull>; ++ pinctrl-names = "default"; ++ vqmmc-supply = <&sd_io_1v8_reg>; ++ vmmc-supply = <&sd_vcc_reg>; ++ bus-width = <8>; ++ sd-uhs-sdr50; ++ sd-uhs-ddr50; ++ sd-uhs-sdr104; ++ mmc-hs200-1_8v; ++ mmc-hs400-1_8v; ++ mmc-hs400-enhanced-strobe; ++ broken-cd; ++ supports-cqe; ++ status = "okay"; ++}; ++ ++&pinctrl_aon { ++ ant_pins: ant_pins { ++ function = "gpio"; ++ pins = "aon_gpio5", "aon_gpio6"; ++ }; ++ ++ /* Slight hack - only one PWM pin (status LED) is usable */ ++ aon_pwm_1pin: aon_pwm_1pin { ++ function = "aon_pwm"; ++ pins = "aon_gpio9"; ++ }; ++}; ++ ++&pinctrl { ++ pwr_button_pins: pwr_button_pins { ++ function = "gpio"; ++ pins = "gpio20"; ++ bias-pull-up; ++ }; ++ ++ wl_on_pins: wl_on_pins { ++ function = "gpio"; ++ pins = "gpio28"; ++ }; ++ ++ bt_shutdown_pins: bt_shutdown_pins { ++ function = "gpio"; ++ pins = "gpio29"; ++ }; ++ ++ emmc_ds_pull: emmc_ds_pull { ++ pins = "emmc_ds"; ++ bias-pull-down; ++ }; ++ ++ emmc_cmddat_pulls: emmc_cmddat_pulls { ++ pins = "emmc_cmd", "emmc_dat0", "emmc_dat1", "emmc_dat2", "emmc_dat3", ++ "emmc_dat4", "emmc_dat5", "emmc_dat6", "emmc_dat7"; ++ bias-pull-up; ++ }; ++}; ++ ++/* uarta communicates with the BT module */ ++&uarta { ++ uart-has-rtscts; ++ auto-flow-control; ++ status = "okay"; ++ clock-frequency = <96000000>; ++ pinctrl-0 = <&uarta_24_pins &bt_shutdown_pins>; ++ pinctrl-names = "default"; ++ ++ bluetooth: bluetooth { ++ compatible = "brcm,bcm43438-bt"; ++ max-speed = <3000000>; ++ shutdown-gpios = <&gio 29 GPIO_ACTIVE_HIGH>; ++ local-bd-address = [ 00 00 00 00 00 00 ]; ++ }; ++}; ++ ++&i2c_rp1boot { ++ clock-frequency = <400000>; ++ pinctrl-0 = <&i2c3_m4_agpio0_pins>; ++ pinctrl-names = "default"; ++}; ++ ++/ { ++ chosen: chosen { ++ bootargs = "reboot=w coherent_pool=1M 8250.nr_uarts=1 pci=pcie_bus_safe"; ++ stdout-path = "serial10:115200n8"; ++ }; ++ ++ fan: cooling_fan { ++ status = "disabled"; ++ compatible = "pwm-fan"; ++ #cooling-cells = <2>; ++ cooling-min-state = <0>; ++ cooling-max-state = <3>; ++ cooling-levels = <0 75 125 175 250>; ++ pwms = <&rp1_pwm1 3 41566 PWM_POLARITY_INVERTED>; ++ rpm-regmap = <&rp1_pwm1>; ++ rpm-offset = <0x3c>; ++ }; ++ ++ pwr_button { ++ compatible = "gpio-keys"; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pwr_button_pins>; ++ status = "okay"; ++ ++ pwr_key: pwr { ++ label = "pwr_button"; ++ // linux,code = <205>; // KEY_SUSPEND ++ linux,code = <116>; // KEY_POWER ++ gpios = <&gio 20 GPIO_ACTIVE_LOW>; ++ debounce-interval = <50>; // ms ++ }; ++ }; ++}; ++ ++&usb { ++ power-domains = <&power RPI_POWER_DOMAIN_USB>; ++}; ++ ++/* SDIO2 drives the WLAN interface */ ++&sdio2 { ++ pinctrl-0 = <&sdio2_30_pins>, <&ant_pins>; ++ pinctrl-names = "default"; ++ bus-width = <4>; ++ vmmc-supply = <&wl_on_reg>; ++ sd-uhs-ddr50; ++ non-removable; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ wifi: wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ local-mac-address = [00 00 00 00 00 00]; ++ }; ++}; ++ ++&rpivid { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ spi10_gpio2: spi10_gpio2 { ++ function = "vc_spi0"; ++ pins = "gpio2", "gpio3", "gpio4"; ++ bias-disable; ++ }; ++ ++ spi10_cs_gpio1: spi10_cs_gpio1 { ++ function = "gpio"; ++ pins = "gpio1"; ++ bias-pull-up; ++ }; ++}; ++ ++spi10_pins: &spi10_gpio2 {}; ++spi10_cs_pins: &spi10_cs_gpio1 {}; ++ ++&spi10 { ++ pinctrl-names = "default"; ++ cs-gpios = <&gio 1 1>; ++ pinctrl-0 = <&spi10_pins &spi10_cs_pins>; ++ ++ spidev10: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <20000000>; ++ status = "okay"; ++ }; ++}; ++ ++// ============================================= ++// Board specific stuff here ++ ++&gio_aon { ++ // Don't use GIO_AON as an interrupt controller because it will ++ // clash with the firmware monitoring the PMIC interrupt via the VPU. ++ ++ /delete-property/ interrupt-controller; ++}; ++ ++&main_aon_irq { ++ // Don't use the MAIN_AON_IRQ interrupt controller because it will ++ // clash with the firmware monitoring the PMIC interrupt via the VPU. ++ ++ status = "disabled"; ++}; ++ ++&rp1_pwm1 { ++ status = "disabled"; ++ pinctrl-0 = <&rp1_pwm1_gpio45>; ++ pinctrl-names = "default"; ++}; ++ ++&thermal_trips { ++ cpu_tepid: cpu-tepid { ++ temperature = <50000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_warm: cpu-warm { ++ temperature = <60000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_hot: cpu-hot { ++ temperature = <67500>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++ ++ cpu_vhot: cpu-vhot { ++ temperature = <75000>; ++ hysteresis = <5000>; ++ type = "active"; ++ }; ++}; ++ ++&cooling_maps { ++ tepid { ++ trip = <&cpu_tepid>; ++ cooling-device = <&fan 1 1>; ++ }; ++ ++ warm { ++ trip = <&cpu_warm>; ++ cooling-device = <&fan 2 2>; ++ }; ++ ++ hot { ++ trip = <&cpu_hot>; ++ cooling-device = <&fan 3 3>; ++ }; ++ ++ vhot { ++ trip = <&cpu_vhot>; ++ cooling-device = <&fan 4 4>; ++ }; ++ ++ melt { ++ trip = <&cpu_crit>; ++ cooling-device = <&fan 4 4>; ++ }; ++}; ++ ++&gio { ++ // The GPIOs above 35 are not used on Pi 5, so shrink the upper bank ++ // to reduce the clutter in gpioinfo/pinctrl ++ brcm,gpio-bank-widths = <32 4>; ++ ++ gpio-line-names = ++ "-", // GPIO_000 ++ "2712_BOOT_CS_N", // GPIO_001 ++ "2712_BOOT_MISO", // GPIO_002 ++ "2712_BOOT_MOSI", // GPIO_003 ++ "2712_BOOT_SCLK", // GPIO_004 ++ "-", // GPIO_005 ++ "-", // GPIO_006 ++ "-", // GPIO_007 ++ "-", // GPIO_008 ++ "-", // GPIO_009 ++ "-", // GPIO_010 ++ "-", // GPIO_011 ++ "-", // GPIO_012 ++ "-", // GPIO_013 ++ "-", // GPIO_014 ++ "-", // GPIO_015 ++ "-", // GPIO_016 ++ "-", // GPIO_017 ++ "-", // GPIO_018 ++ "-", // GPIO_019 ++ "PWR_GPIO", // GPIO_020 ++ "2712_G21_FS", // GPIO_021 ++ "-", // GPIO_022 ++ "-", // GPIO_023 ++ "BT_RTS", // GPIO_024 ++ "BT_CTS", // GPIO_025 ++ "BT_TXD", // GPIO_026 ++ "BT_RXD", // GPIO_027 ++ "WL_ON", // GPIO_028 ++ "BT_ON", // GPIO_029 ++ "WIFI_SDIO_CLK", // GPIO_030 ++ "WIFI_SDIO_CMD", // GPIO_031 ++ "WIFI_SDIO_D0", // GPIO_032 ++ "WIFI_SDIO_D1", // GPIO_033 ++ "WIFI_SDIO_D2", // GPIO_034 ++ "WIFI_SDIO_D3"; // GPIO_035 ++}; ++ ++&gio_aon { ++ gpio-line-names = ++ "RP1_SDA", // AON_GPIO_00 ++ "RP1_SCL", // AON_GPIO_01 ++ "RP1_RUN", // AON_GPIO_02 ++ "SD_IOVDD_SEL", // AON_GPIO_03 ++ "SD_PWR_ON", // AON_GPIO_04 ++ "ANT1", // AON_GPIO_05 ++ "ANT2", // AON_GPIO_06 ++ "-", // AON_GPIO_07 ++ "2712_WAKE", // AON_GPIO_08 ++ "2712_STAT_LED", // AON_GPIO_09 ++ "-", // AON_GPIO_10 ++ "-", // AON_GPIO_11 ++ "PMIC_INT", // AON_GPIO_12 ++ "UART_TX_FS", // AON_GPIO_13 ++ "UART_RX_FS", // AON_GPIO_14 ++ "-", // AON_GPIO_15 ++ "-", // AON_GPIO_16 ++ ++ // Pad bank0 out to 32 entries ++ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ++ ++ "HDMI0_SCL", // AON_SGPIO_00 ++ "HDMI0_SDA", // AON_SGPIO_01 ++ "HDMI1_SCL", // AON_SGPIO_02 ++ "HDMI1_SDA", // AON_SGPIO_03 ++ "PMIC_SCL", // AON_SGPIO_04 ++ "PMIC_SDA"; // AON_SGPIO_05 ++ ++ rp1_run_hog { ++ gpio-hog; ++ gpios = <2 GPIO_ACTIVE_HIGH>; ++ output-high; ++ line-name = "RP1 RUN pin"; ++ }; ++ ++ ant1: ant1-hog { ++ gpio-hog; ++ gpios = <5 GPIO_ACTIVE_HIGH>; ++ /* internal antenna enabled */ ++ output-high; ++ line-name = "ant1"; ++ }; ++ ++ ant2: ant2-hog { ++ gpio-hog; ++ gpios = <6 GPIO_ACTIVE_HIGH>; ++ /* external antenna disabled */ ++ output-low; ++ line-name = "ant2"; ++ }; ++}; ++ ++&rp1_gpio { ++ gpio-line-names = ++ "ID_SDA", // GPIO0 ++ "ID_SCL", // GPIO1 ++ "GPIO2", // GPIO2 ++ "GPIO3", // GPIO3 ++ "GPIO4", // GPIO4 ++ "GPIO5", // GPIO5 ++ "GPIO6", // GPIO6 ++ "GPIO7", // GPIO7 ++ "GPIO8", // GPIO8 ++ "GPIO9", // GPIO9 ++ "GPIO10", // GPIO10 ++ "GPIO11", // GPIO11 ++ "GPIO12", // GPIO12 ++ "GPIO13", // GPIO13 ++ "GPIO14", // GPIO14 ++ "GPIO15", // GPIO15 ++ "GPIO16", // GPIO16 ++ "GPIO17", // GPIO17 ++ "GPIO18", // GPIO18 ++ "GPIO19", // GPIO19 ++ "GPIO20", // GPIO20 ++ "GPIO21", // GPIO21 ++ "GPIO22", // GPIO22 ++ "GPIO23", // GPIO23 ++ "GPIO24", // GPIO24 ++ "GPIO25", // GPIO25 ++ "GPIO26", // GPIO26 ++ "GPIO27", // GPIO27 ++ ++ "PCIE_PWR_EN", // GPIO28 ++ "FAN_TACH", // GPIO29 ++ "HOST_SDA", // GPIO30 ++ "HOST_SCL", // GPIO31 ++ "ETH_RST_N", // GPIO32 ++ "PCIE_DET_WAKE", // GPIO33 ++ ++ "CD0_IO0_MICCLK", // GPIO34 ++ "CD0_IO0_MICDAT0", // GPIO35 ++ "RP1_PCIE_CLKREQ_N", // GPIO36 ++ "ETH_IRQ_N", // GPIO37 ++ "SDA0", // GPIO38 ++ "SCL0", // GPIO39 ++ "-", // GPIO40 ++ "-", // GPIO41 ++ "USB_VBUS_EN", // GPIO42 ++ "USB_OC_N", // GPIO43 ++ "RP1_STAT_LED", // GPIO44 ++ "FAN_PWM", // GPIO45 ++ "-", // GPIO46 ++ "2712_WAKE", // GPIO47 ++ "-", // GPIO48 ++ "-", // GPIO49 ++ "-", // GPIO50 ++ "-", // GPIO51 ++ "-", // GPIO52 ++ "-"; // GPIO53 ++ ++ usb_vbus_pins: usb_vbus_pins { ++ function = "vbus1"; ++ pins = "gpio42", "gpio43"; ++ }; ++}; ++ ++/ { ++ aliases: aliases { ++ blconfig = &blconfig; ++ blpubkey = &blpubkey; ++ bluetooth = &bluetooth; ++ console = &uart10; ++ ethernet0 = &rp1_eth; ++ wifi0 = &wifi; ++ fb = &fb; ++ mailbox = &mailbox; ++ mmc0 = &sdio1; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ uart2 = &uart2; ++ uart3 = &uart3; ++ uart4 = &uart4; ++ uart10 = &uart10; ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ serial10 = &uart10; ++ i2c = &i2c_arm; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ i2c6 = &i2c6; ++ i2c10 = &i2c_rp1boot; ++ // Bit-bashed i2c_gpios start at 10 ++ spi0 = &spi0; ++ spi1 = &spi1; ++ spi2 = &spi2; ++ spi3 = &spi3; ++ spi4 = &spi4; ++ spi5 = &spi5; ++ spi10 = &spi10; ++ gpio0 = &gpio; ++ gpio1 = &gio; ++ gpio2 = &gio_aon; ++ gpio3 = &pinctrl; ++ gpio4 = &pinctrl_aon; ++ usb0 = &rp1_usb0; ++ usb1 = &rp1_usb1; ++ drm-dsi1 = &dsi0; ++ drm-dsi2 = &dsi1; ++ }; ++ ++ __overrides__ { ++ bdaddr = <&bluetooth>, "local-bd-address["; ++ button_debounce = <&pwr_key>, "debounce-interval:0"; ++ cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status"; ++ uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0; ++ i2c0 = <&i2c0>, "status"; ++ i2c1 = <&i2c1>, "status"; ++ i2c = <&i2c1>, "status"; ++ i2c_arm = <&i2c_arm>, "status"; ++ i2c_vc = <&i2c_vc>, "status"; ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status"; ++ i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status"; ++ i2c0_baudrate = <&i2c0>, "clock-frequency:0"; ++ i2c1_baudrate = <&i2c1>, "clock-frequency:0"; ++ i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; ++ i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; ++ i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; ++ krnbt = <&bluetooth>, "status"; ++ nvme = <&pciex1>, "status"; ++ pciex1 = <&pciex1>, "status"; ++ pciex1_gen = <&pciex1> , "max-link-speed:0"; ++ pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; ++ pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; ++ pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; ++ random = <&random>, "status"; ++ rtc = <&rpi_rtc>, "status"; ++ rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; ++ spi = <&spi0>, "status"; ++ suspend = <&pwr_key>, "linux,code:0=205"; ++ uart0 = <&uart0>, "status"; ++ wifiaddr = <&wifi>, "local-mac-address["; ++ ++ act_led_activelow = <&led_act>, "active-low?"; ++ act_led_trigger = <&led_act>, "linux,default-trigger"; ++ pwr_led_activelow = <&led_pwr>, "gpios:8"; ++ pwr_led_trigger = <&led_pwr>, "linux,default-trigger"; ++ eth_led0 = <&phy1>,"led-modes:0"; ++ eth_led1 = <&phy1>,"led-modes:4"; ++ drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; ++ drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; ++ drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; ++ drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; ++ drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0; ++ drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1; ++ drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi; ++ drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; ++ drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0; ++ drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; ++ drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; ++ drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; ++ ++ ant1 = <&ant1>,"output-high?=on", ++ <&ant1>, "output-low?=off", ++ <&ant2>, "output-high?=off", ++ <&ant2>, "output-low?=on"; ++ ant2 = <&ant1>,"output-high?=off", ++ <&ant1>, "output-low?=on", ++ <&ant2>, "output-high?=on", ++ <&ant2>, "output-low?=off"; ++ noant = <&ant1>,"output-high?=off", ++ <&ant1>, "output-low?=on", ++ <&ant2>, "output-high?=off", ++ <&ant2>, "output-low?=on"; ++ ++ fan_temp0 = <&cpu_tepid>,"temperature:0"; ++ fan_temp1 = <&cpu_warm>,"temperature:0"; ++ fan_temp2 = <&cpu_hot>,"temperature:0"; ++ fan_temp3 = <&cpu_vhot>,"temperature:0"; ++ fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0"; ++ fan_temp1_hyst = <&cpu_warm>,"hysteresis:0"; ++ fan_temp2_hyst = <&cpu_hot>,"hysteresis:0"; ++ fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0"; ++ fan_temp0_speed = <&fan>, "cooling-levels:4"; ++ fan_temp1_speed = <&fan>, "cooling-levels:8"; ++ fan_temp2_speed = <&fan>, "cooling-levels:12"; ++ fan_temp3_speed = <&fan>, "cooling-levels:16"; ++ }; ++}; +--- a/arch/arm64/boot/dts/broadcom/bcm2712d0-rpi-5-b.dts ++++ b/arch/arm64/boot/dts/broadcom/bcm2712d0-rpi-5-b.dts +@@ -1,2 +1,107 @@ + // SPDX-License-Identifier: GPL-2.0 +-#include "../../../../arm/boot/dts/broadcom/bcm2712d0-rpi-5-b.dts" ++#include "bcm2712-rpi-5-b.dts" ++ ++&gio { ++ brcm,gpio-bank-widths = <32 4>; ++ ++ gpio-line-names = ++ "", // GPIO_000 ++ "2712_BOOT_CS_N", // GPIO_001 ++ "2712_BOOT_MISO", // GPIO_002 ++ "2712_BOOT_MOSI", // GPIO_003 ++ "2712_BOOT_SCLK", // GPIO_004 ++ "", // GPIO_005 ++ "", // GPIO_006 ++ "", // GPIO_007 ++ "", // GPIO_008 ++ "", // GPIO_009 ++ "", // GPIO_010 ++ "", // GPIO_011 ++ "", // GPIO_012 ++ "", // GPIO_013 ++ "PCIE_SDA", // GPIO_014 ++ "PCIE_SCL", // GPIO_015 ++ "", // GPIO_016 ++ "", // GPIO_017 ++ "-", // GPIO_018 ++ "-", // GPIO_019 ++ "PWR_GPIO", // GPIO_020 ++ "2712_G21_FS", // GPIO_021 ++ "-", // GPIO_022 ++ "-", // GPIO_023 ++ "BT_RTS", // GPIO_024 ++ "BT_CTS", // GPIO_025 ++ "BT_TXD", // GPIO_026 ++ "BT_RXD", // GPIO_027 ++ "WL_ON", // GPIO_028 ++ "BT_ON", // GPIO_029 ++ "WIFI_SDIO_CLK", // GPIO_030 ++ "WIFI_SDIO_CMD", // GPIO_031 ++ "WIFI_SDIO_D0", // GPIO_032 ++ "WIFI_SDIO_D1", // GPIO_033 ++ "WIFI_SDIO_D2", // GPIO_034 ++ "WIFI_SDIO_D3"; // GPIO_035 ++}; ++ ++&gio_aon { ++ brcm,gpio-bank-widths = <15 6>; ++ ++ gpio-line-names = ++ "RP1_SDA", // AON_GPIO_00 ++ "RP1_SCL", // AON_GPIO_01 ++ "RP1_RUN", // AON_GPIO_02 ++ "SD_IOVDD_SEL", // AON_GPIO_03 ++ "SD_PWR_ON", // AON_GPIO_04 ++ "SD_CDET_N", // AON_GPIO_05 ++ "SD_FLG_N", // AON_GPIO_06 ++ "", // AON_GPIO_07 ++ "2712_WAKE", // AON_GPIO_08 ++ "2712_STAT_LED", // AON_GPIO_09 ++ "", // AON_GPIO_10 ++ "", // AON_GPIO_11 ++ "PMIC_INT", // AON_GPIO_12 ++ "UART_TX_FS", // AON_GPIO_13 ++ "UART_RX_FS", // AON_GPIO_14 ++ "", // AON_GPIO_15 ++ "", // AON_GPIO_16 ++ ++ // Pad bank0 out to 32 entries ++ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ++ ++ "HDMI0_SCL", // AON_SGPIO_00 ++ "HDMI0_SDA", // AON_SGPIO_01 ++ "HDMI1_SCL", // AON_SGPIO_02 ++ "HDMI1_SDA", // AON_SGPIO_03 ++ "PMIC_SCL", // AON_SGPIO_04 ++ "PMIC_SDA"; // AON_SGPIO_05 ++}; ++ ++&pinctrl { ++ compatible = "brcm,bcm2712d0-pinctrl"; ++ reg = <0x7d504100 0x20>; ++}; ++ ++&pinctrl_aon { ++ compatible = "brcm,bcm2712d0-aon-pinctrl"; ++ reg = <0x7d510700 0x1c>; ++}; ++ ++&vc4 { ++ compatible = "brcm,bcm2712d0-vc6"; ++}; ++ ++&uart10 { ++ interrupts = ; ++}; ++ ++&spi10 { ++ dmas = <&dma40 3>, <&dma40 4>; ++}; ++ ++&hdmi0 { ++ dmas = <&dma40 (12|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; ++}; ++ ++&hdmi1 { ++ dmas = <&dma40 (13|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm2712-rpi.dtsi ++++ /dev/null +@@ -1,351 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +- +-#include +- +-&soc { +- firmware: firmware { +- compatible = "raspberrypi,bcm2835-firmware", "simple-mfd"; +- #address-cells = <1>; +- #size-cells = <1>; +- +- mboxes = <&mailbox>; +- dma-ranges; +- +- firmware_clocks: clocks { +- compatible = "raspberrypi,firmware-clocks"; +- #clock-cells = <1>; +- }; +- +- reset: reset { +- compatible = "raspberrypi,firmware-reset"; +- #reset-cells = <1>; +- }; +- +- vcio: vcio { +- compatible = "raspberrypi,vcio"; +- }; +- }; +- +- power: power { +- compatible = "raspberrypi,bcm2835-power"; +- firmware = <&firmware>; +- #power-domain-cells = <1>; +- }; +- +- fb: fb { +- compatible = "brcm,bcm2708-fb"; +- firmware = <&firmware>; +- status = "okay"; +- }; +- +- rpi_rtc: rpi_rtc { +- compatible = "raspberrypi,rpi-rtc"; +- firmware = <&firmware>; +- status = "okay"; +- trickle-charge-microvolt = <0>; +- }; +- +- nvmem { +- compatible = "simple-bus"; +- #address-cells = <1>; +- #size-cells = <1>; +- +- nvmem_otp: nvmem_otp { +- compatible = "raspberrypi,rpi-otp"; +- firmware = <&firmware>; +- reg = <0 192>; +- status = "okay"; +- }; +- +- nvmem_cust: nvmem_cust { +- compatible = "raspberrypi,rpi-otp"; +- firmware = <&firmware>; +- reg = <1 8>; +- status = "okay"; +- }; +- +- nvmem_mac: nvmem_mac { +- compatible = "raspberrypi,rpi-otp"; +- firmware = <&firmware>; +- reg = <2 6>; +- status = "okay"; +- }; +- +- nvmem_priv: nvmem_priv { +- compatible = "raspberrypi,rpi-otp"; +- firmware = <&firmware>; +- reg = <3 16>; +- status = "okay"; +- }; +- }; +- +- /* Define these notional regulators for use by overlays, etc. */ +- vdd_3v3_reg: fixedregulator_3v3 { +- compatible = "regulator-fixed"; +- regulator-always-on; +- regulator-max-microvolt = <3300000>; +- regulator-min-microvolt = <3300000>; +- regulator-name = "3v3"; +- }; +- +- vdd_5v0_reg: fixedregulator_5v0 { +- compatible = "regulator-fixed"; +- regulator-always-on; +- regulator-max-microvolt = <5000000>; +- regulator-min-microvolt = <5000000>; +- regulator-name = "5v0"; +- }; +-}; +- +-/ { +- __overrides__ { +- arm_freq; +- axiperf = <&axiperf>,"status"; +- +- nvmem_cust_rw = <&nvmem_cust>,"rw?"; +- nvmem_priv_rw = <&nvmem_priv>,"rw?"; +- nvmem_mac_rw = <&nvmem_mac>,"rw?"; +- strict_gpiod = <&chosen>, "bootargs=pinctrl_rp1.persist_gpio_outputs=n"; +- +- cam0_reg = <&cam0_reg>,"status"; +- cam0_reg_gpio = <&cam0_reg>,"gpio:4", +- <&cam0_reg>,"gpio:0=", <&gpio>; +- cam1_reg = <&cam1_reg>,"status"; +- cam1_reg_gpio = <&cam1_reg>,"gpio:4", +- <&cam1_reg>,"gpio:0=", <&gpio>; +- +- }; +-}; +- +-pciex1: &pcie1 { }; +-pciex4: &pcie2 { }; +- +-&dma32 { +- /* The VPU firmware uses DMA channel 11 for VCHIQ */ +- brcm,dma-channel-mask = <0x03f>; +-}; +- +-&dma40 { +- /* The VPU firmware DMA channel 11 for VCHIQ */ +- brcm,dma-channel-mask = <0x07c0>; +-}; +- +-&hdmi0 { +- dmas = <&dma40 (10|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; +-}; +- +-&hdmi1 { +- dmas = <&dma40 (17|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; +-}; +- +-&spi10 { +- dmas = <&dma40 6>, <&dma40 7>; +- dma-names = "tx", "rx"; +-}; +- +-&usb { +- power-domains = <&power RPI_POWER_DOMAIN_USB>; +-}; +- +-&rmem { +- /* +- * RPi5's co-processor will copy the board's bootloader configuration +- * into memory for the OS to consume. It'll also update this node with +- * its placement information. +- */ +- blconfig: nvram@0 { +- compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; +- #address-cells = <1>; +- #size-cells = <1>; +- reg = <0x0 0x0 0x0>; +- no-map; +- status = "disabled"; +- }; +- /* +- * RPi5 will copy the binary public key blob (if present) from the bootloader +- * into memory for use by the OS. +- */ +- blpubkey: nvram@1 { +- compatible = "raspberrypi,bootloader-public-key", "nvmem-rmem"; +- #address-cells = <1>; +- #size-cells = <1>; +- reg = <0x0 0x0 0x0>; +- no-map; +- status = "disabled"; +- }; +-}; +- +-&rp1_adc { +- status = "okay"; +-}; +- +-/* Add some gpiomem nodes to make the devices accessible to userspace. +- * /dev/gpiomem should expose the registers for the interface with DT alias +- * gpio. +- */ +- +-&rp1 { +- gpiomem@d0000 { +- /* Export IO_BANKs, RIO_BANKs and PADS_BANKs to userspace */ +- compatible = "raspberrypi,gpiomem"; +- reg = <0xc0 0x400d0000 0x0 0x30000>; +- chardev-name = "gpiomem0"; +- }; +-}; +- +-&soc { +- gpiomem@7d508500 { +- compatible = "raspberrypi,gpiomem"; +- reg = <0x7d508500 0x40>; +- chardev-name = "gpiomem1"; +- }; +- +- gpiomem@7d517c00 { +- compatible = "raspberrypi,gpiomem"; +- reg = <0x7d517c00 0x40>; +- chardev-name = "gpiomem2"; +- }; +- +- gpiomem@7d504100 { +- compatible = "raspberrypi,gpiomem"; +- reg = <0x7d504100 0x20>; +- chardev-name = "gpiomem3"; +- }; +- +- gpiomem@7d510700 { +- compatible = "raspberrypi,gpiomem"; +- reg = <0x7d510700 0x20>; +- chardev-name = "gpiomem4"; +- }; +- +- sound: sound { +- status = "disabled"; +- }; +-}; +- +-i2c0: &rp1_i2c0 { }; +-i2c1: &rp1_i2c1 { }; +-i2c2: &rp1_i2c2 { }; +-i2c3: &rp1_i2c3 { }; +-i2c4: &rp1_i2c4 { }; +-i2c5: &rp1_i2c5 { }; +-i2c6: &rp1_i2c6 { }; +-i2s: &rp1_i2s0 { }; +-i2s_clk_producer: &rp1_i2s0 { }; +-i2s_clk_consumer: &rp1_i2s1 { }; +-pwm0: &rp1_pwm0 { }; +-pwm1: &rp1_pwm1 { }; +-pwm: &pwm0 { }; +-spi0: &rp1_spi0 { }; +-spi1: &rp1_spi1 { }; +-spi2: &rp1_spi2 { }; +-spi3: &rp1_spi3 { }; +-spi4: &rp1_spi4 { }; +-spi5: &rp1_spi5 { }; +- +-uart0_pins: &rp1_uart0_14_15 {}; +-uart0_ctsrts_pins: &rp1_uart0_ctsrts_16_17 {}; +-uart0: &rp1_uart0 { +- pinctrl-0 = <&uart0_pins>; +-}; +- +-uart1_pins: &rp1_uart1_0_1 {}; +-uart1_ctsrts_pins: &rp1_uart1_ctsrts_2_3 {}; +-uart1: &rp1_uart1 { }; +- +-uart2_pins: &rp1_uart2_4_5 {}; +-uart2_ctsrts_pins: &rp1_uart2_ctsrts_6_7 {}; +-uart2: &rp1_uart2 { }; +- +-uart3_pins: &rp1_uart3_8_9 {}; +-uart3_ctsrts_pins: &rp1_uart3_ctsrts_10_11 {}; +-uart3: &rp1_uart3 { }; +- +-uart4_pins: &rp1_uart4_12_13 {}; +-uart4_ctsrts_pins: &rp1_uart4_ctsrts_14_15 {}; +-uart4: &rp1_uart4 { }; +- +-i2c0_pins: &rp1_i2c0_0_1 {}; +-i2c_vc: &i2c0 { // This is pins 27,28 on the header (not MIPI) +- pinctrl-0 = <&i2c0_pins>; +- pinctrl-names = "default"; +- clock-frequency = <100000>; +-}; +- +-i2c1_pins: &rp1_i2c1_2_3 {}; +-i2c_arm: &i2c1 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c1_pins>; +- clock-frequency = <100000>; +-}; +- +-i2c2_pins: &rp1_i2c2_4_5 {}; +-&i2c2 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c2_pins>; +-}; +- +-i2c3_pins: &rp1_i2c3_6_7 {}; +-&i2c3 { +- pinctrl-names = "default"; +- pinctrl-0 = <&i2c3_pins>; +-}; +- +-&i2s_clk_producer { +- pinctrl-names = "default"; +- pinctrl-0 = <&rp1_i2s0_18_21>; +-}; +- +-&i2s_clk_consumer { +- pinctrl-names = "default"; +- pinctrl-0 = <&rp1_i2s1_18_21>; +-}; +- +-spi0_pins: &rp1_spi0_gpio9 {}; +-spi0_cs_pins: &rp1_spi0_cs_gpio7 {}; +- +-&spi0 { +- pinctrl-names = "default"; +- pinctrl-0 = <&spi0_pins &spi0_cs_pins>; +- cs-gpios = <&gpio 8 1>, <&gpio 7 1>; +- +- spidev0: spidev@0 { +- compatible = "spidev"; +- reg = <0>; /* CE0 */ +- #address-cells = <1>; +- #size-cells = <0>; +- spi-max-frequency = <125000000>; +- }; +- +- spidev1: spidev@1 { +- compatible = "spidev"; +- reg = <1>; /* CE1 */ +- #address-cells = <1>; +- #size-cells = <0>; +- spi-max-frequency = <125000000>; +- }; +-}; +- +-spi2_pins: &rp1_spi2_gpio1 {}; +-&spi2 { +- pinctrl-names = "default"; +- pinctrl-0 = <&spi2_pins>; +-}; +- +-spi3_pins: &rp1_spi3_gpio5 {}; +-&spi3 { +- pinctrl-names = "default"; +- pinctrl-0 = <&spi3_pins>; +-}; +- +-spi4_pins: &rp1_spi4_gpio9 {}; +-&spi4 { +- pinctrl-names = "default"; +- pinctrl-0 = <&spi4_pins>; +-}; +- +-spi5_pins: &rp1_spi5_gpio13 {}; +-&spi5 { +- pinctrl-names = "default"; +- pinctrl-0 = <&spi5_pins>; +-}; +--- a/arch/arm/boot/dts/broadcom/bcm2712.dtsi ++++ /dev/null +@@ -1,1302 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-#include +-#include +-#include +- +-/ { +- compatible = "brcm,bcm2712", "brcm,bcm2711"; +- model = "BCM2712"; +- +- #address-cells = <2>; +- #size-cells = <1>; +- +- interrupt-parent = <&gicv2>; +- +- rmem: reserved-memory { +- #address-cells = <2>; +- #size-cells = <1>; +- ranges; +- +- atf@0 { +- reg = <0x0 0x0 0x80000>; +- no-map; +- }; +- +- cma: linux,cma { +- compatible = "shared-dma-pool"; +- size = <0x4000000>; /* 64MB */ +- reusable; +- linux,cma-default; +- +- /* +- * arm64 reserves the CMA by default somewhere in +- * ZONE_DMA32, that's not good enough for the BCM2711 +- * as some devices can only address the lower 1G of +- * memory (ZONE_DMA). +- */ +- alloc-ranges = <0x0 0x00000000 0x40000000>; +- }; +- }; +- +- thermal-zones { +- cpu_thermal: cpu-thermal { +- polling-delay-passive = <2000>; +- polling-delay = <1000>; +- coefficients = <(-550) 450000>; +- thermal-sensors = <&thermal>; +- +- thermal_trips: trips { +- cpu_crit: cpu-crit { +- temperature = <110000>; +- hysteresis = <0>; +- type = "critical"; +- }; +- }; +- +- cooling_maps: cooling-maps { +- }; +- }; +- }; +- +- clk_27MHz: clk-27M { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <27000000>; +- clock-output-names = "27MHz-clock"; +- }; +- +- clk_108MHz: clk-108M { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <108000000>; +- clock-output-names = "108MHz-clock"; +- }; +- +- hvs: hvs@107c580000 { +- compatible = "brcm,bcm2712-hvs"; +- reg = <0x10 0x7c580000 0x1a000>; +- interrupt-parent = <&disp_intr>; +- interrupts = <2>, <9>, <16>; +- interrupt-names = "ch0-eof", "ch1-eof", "ch2-eof"; +- //iommus = <&iommu4>; +- status = "disabled"; +- }; +- +- soc: soc { +- compatible = "simple-bus"; +- #address-cells = <1>; +- #size-cells = <1>; +- +- ranges = <0x7c000000 0x10 0x7c000000 0x04000000>; +- /* Emulate a contiguous 30-bit address range for DMA */ +- dma-ranges = <0xc0000000 0x00 0x00000000 0x40000000>, +- <0x7c000000 0x10 0x7c000000 0x04000000>; +- +- system_timer: timer@7c003000 { +- compatible = "brcm,bcm2835-system-timer"; +- reg = <0x7c003000 0x1000>; +- interrupts = , +- , +- , +- ; +- clock-frequency = <1000000>; +- }; +- +- firmwarekms: firmwarekms@7d503000 { +- compatible = "raspberrypi,rpi-firmware-kms-2712"; +- /* SUN_L2 interrupt reg */ +- reg = <0x7d503000 0x18>; +- interrupt-parent = <&cpu_l2_irq>; +- interrupts = <19>; +- brcm,firmware = <&firmware>; +- status = "disabled"; +- }; +- +- axiperf: axiperf { +- compatible = "brcm,bcm2712-axiperf"; +- reg = <0x7c012800 0x100>, +- <0x7e000000 0x100>; +- firmware = <&firmware>; +- status = "disabled"; +- }; +- +- mailbox: mailbox@7c013880 { +- compatible = "brcm,bcm2835-mbox"; +- reg = <0x7c013880 0x40>; +- interrupts = ; +- #mbox-cells = <0>; +- }; +- +- pixelvalve0: pixelvalve@7c410000 { +- compatible = "brcm,bcm2712-pixelvalve0"; +- reg = <0x7c410000 0x100>; +- interrupts = ; +- status = "disabled"; +- }; +- +- pixelvalve1: pixelvalve@7c411000 { +- compatible = "brcm,bcm2712-pixelvalve1"; +- reg = <0x7c411000 0x100>; +- interrupts = ; +- status = "disabled"; +- }; +- +- mop: mop@7c500000 { +- compatible = "brcm,bcm2712-mop"; +- reg = <0x7c500000 0x28>; +- interrupt-parent = <&disp_intr>; +- interrupts = <1>; +- status = "disabled"; +- }; +- +- moplet: moplet@7c501000 { +- compatible = "brcm,bcm2712-moplet"; +- reg = <0x7c501000 0x20>; +- interrupt-parent = <&disp_intr>; +- interrupts = <0>; +- status = "disabled"; +- }; +- +- disp_intr: interrupt-controller@7c502000 { +- compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; +- reg = <0x7c502000 0x30>; +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <1>; +- status = "disabled"; +- }; +- +- dvp: clock@7c700000 { +- compatible = "brcm,brcm2711-dvp"; +- reg = <0x7c700000 0x10>; +- clocks = <&clk_108MHz>; +- #clock-cells = <1>; +- #reset-cells = <1>; +- }; +- +- /* +- * This node is the provider for the enable-method for +- * bringing up secondary cores. +- */ +- local_intc: local_intc@7cd00000 { +- compatible = "brcm,bcm2836-l1-intc"; +- reg = <0x7cd00000 0x100>; +- }; +- +- uart0: serial@7d001000 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x7d001000 0x200>; +- interrupts = ; +- clocks = <&clk_uart>, +- <&clk_vpu>; +- clock-names = "uartclk", "apb_pclk"; +- arm,primecell-periphid = <0x00241011>; +- status = "disabled"; +- }; +- +- uart2: serial@7d001400 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x7d001400 0x200>; +- interrupts = ; +- clocks = <&clk_uart>, +- <&clk_vpu>; +- clock-names = "uartclk", "apb_pclk"; +- arm,primecell-periphid = <0x00241011>; +- status = "disabled"; +- }; +- +- uart5: serial@7d001a00 { +- compatible = "arm,pl011", "arm,primecell"; +- reg = <0x7d001a00 0x200>; +- interrupts = ; +- clocks = <&clk_uart>, +- <&clk_vpu>; +- clock-names = "uartclk", "apb_pclk"; +- arm,primecell-periphid = <0x00241011>; +- status = "disabled"; +- }; +- +- sdhost: mmc@7d002000 { +- compatible = "brcm,bcm2835-sdhost"; +- reg = <0x7d002000 0x100>; +- //interrupts = ; +- clocks = <&clk_vpu>; +- status = "disabled"; +- }; +- +- i2s: i2s@7d003000 { +- compatible = "brcm,bcm2835-i2s"; +- reg = <0x7d003000 0x24>; +- //clocks = <&cprman BCM2835_CLOCK_PCM>; +- status = "disabled"; +- }; +- +- spi0: spi@7d004000 { +- compatible = "brcm,bcm2835-spi"; +- reg = <0x7d004000 0x200>; +- interrupts = ; +- clocks = <&clk_vpu>; +- num-cs = <1>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- spi3: spi@7d004600 { +- compatible = "brcm,bcm2835-spi"; +- reg = <0x7d004600 0x0200>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- spi4: spi@7d004800 { +- compatible = "brcm,bcm2835-spi"; +- reg = <0x7d004800 0x0200>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- spi5: spi@7d004a00 { +- compatible = "brcm,bcm2835-spi"; +- reg = <0x7d004a00 0x0200>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- spi6: spi@7d004c00 { +- compatible = "brcm,bcm2835-spi"; +- reg = <0x7d004c00 0x0200>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c0: i2c@7d005000 { +- compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; +- reg = <0x7d005000 0x20>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c3: i2c@7d005600 { +- compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; +- reg = <0x7d005600 0x20>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c4: i2c@7d005800 { +- compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; +- reg = <0x7d005800 0x20>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c5: i2c@7d005a00 { +- compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; +- reg = <0x7d005a00 0x20>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c6: i2c@7d005c00 { +- compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; +- reg = <0x7d005c00 0x20>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- i2c8: i2c@7d005e00 { +- compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; +- reg = <0x7d005e00 0x20>; +- interrupts = ; +- clocks = <&clk_vpu>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- pwm0: pwm@7d00c000 { +- compatible = "brcm,bcm2835-pwm"; +- reg = <0x7d00c000 0x28>; +- assigned-clock-rates = <50000000>; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pwm1: pwm@7d00c800 { +- compatible = "brcm,bcm2835-pwm"; +- reg = <0x7d00c800 0x28>; +- assigned-clock-rates = <50000000>; +- #pwm-cells = <3>; +- status = "disabled"; +- }; +- +- pm: watchdog@7d200000 { +- compatible = "brcm,bcm2712-pm"; +- reg = <0x7d200000 0x308>; +- reg-names = "pm"; +- #power-domain-cells = <1>; +- #reset-cells = <1>; +- //clocks = <&cprman BCM2835_CLOCK_V3D>, +- // <&cprman BCM2835_CLOCK_PERI_IMAGE>, +- // <&cprman BCM2835_CLOCK_H264>, +- // <&cprman BCM2835_CLOCK_ISP>; +- clock-names = "v3d", "peri_image", "h264", "isp"; +- system-power-controller; +- }; +- +- cprman: cprman@7d202000 { +- compatible = "brcm,bcm2711-cprman"; +- reg = <0x7d202000 0x2000>; +- #clock-cells = <1>; +- +- /* CPRMAN derives almost everything from the +- * platform's oscillator. However, the DSI +- * pixel clocks come from the DSI analog PHY. +- */ +- clocks = <&clk_osc>; +- status = "disabled"; +- }; +- +- random: rng@7d208000 { +- compatible = "brcm,bcm2711-rng200"; +- reg = <0x7d208000 0x28>; +- status = "okay"; +- }; +- +- cpu_l2_irq: intc@7d503000 { +- compatible = "brcm,l2-intc"; +- reg = <0x7d503000 0x18>; +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <1>; +- }; +- +- pinctrl: pinctrl@7d504100 { +- compatible = "brcm,bcm2712-pinctrl"; +- reg = <0x7d504100 0x30>; +- +- uarta_24_pins: uarta_24_pins { +- pin_rts { +- function = "uart0"; +- pins = "gpio24"; +- bias-disable; +- }; +- pin_cts { +- function = "uart0"; +- pins = "gpio25"; +- bias-pull-up; +- }; +- pin_txd { +- function = "uart0"; +- pins = "gpio26"; +- bias-disable; +- }; +- pin_rxd { +- function = "uart0"; +- pins = "gpio27"; +- bias-pull-up; +- }; +- }; +- +- sdio2_30_pins: sdio2_30_pins { +- pin_clk { +- function = "sd2"; +- pins = "gpio30"; +- bias-disable; +- }; +- pin_cmd { +- function = "sd2"; +- pins = "gpio31"; +- bias-pull-up; +- }; +- pins_dat { +- function = "sd2"; +- pins = "gpio32", "gpio33", "gpio34", "gpio35"; +- bias-pull-up; +- }; +- }; +- }; +- +- ddc0: i2c@7d508200 { +- compatible = "brcm,brcmstb-i2c"; +- reg = <0x7d508200 0x58>; +- interrupt-parent = <&bsc_irq>; +- interrupts = <1>; +- clock-frequency = <97500>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- ddc1: i2c@7d508280 { +- compatible = "brcm,brcmstb-i2c"; +- reg = <0x7d508280 0x58>; +- interrupt-parent = <&bsc_irq>; +- interrupts = <2>; +- clock-frequency = <97500>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- bscd: i2c@7d508300 { +- compatible = "brcm,brcmstb-i2c"; +- reg = <0x7d508300 0x58>; +- interrupt-parent = <&bsc_irq>; +- interrupts = <0>; +- clock-frequency = <200000>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- bsc_irq: intc@7d508380 { +- compatible = "brcm,bcm7271-l2-intc"; +- reg = <0x7d508380 0x10>; +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <1>; +- }; +- +- main_irq: intc@7d508400 { +- compatible = "brcm,bcm7271-l2-intc"; +- reg = <0x7d508400 0x10>; +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <1>; +- }; +- +- gio: gpio@7d508500 { +- compatible = "brcm,brcmstb-gpio"; +- reg = <0x7d508500 0x40>; +- interrupt-parent = <&main_irq>; +- interrupts = <0>; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- brcm,gpio-bank-widths = <32 22>; +- brcm,gpio-direct; +- }; +- +- uarta: serial@7d50c000 { +- compatible = "brcm,bcm7271-uart"; +- reg = <0x7d50c000 0x20>; +- reg-names = "uart"; +- reg-shift = <2>; +- reg-io-width = <4>; +- interrupts = ; +- skip-init; +- status = "disabled"; +- }; +- +- uartb: serial@7d50d000 { +- compatible = "brcm,bcm7271-uart"; +- reg = <0x7d50d000 0x20>; +- reg-names = "uart"; +- reg-shift = <2>; +- reg-io-width = <4>; +- interrupts = ; +- skip-init; +- status = "disabled"; +- }; +- +- aon_intr: interrupt-controller@7d510600 { +- compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; +- reg = <0x7d510600 0x30>; +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <1>; +- status = "disabled"; +- }; +- +- pinctrl_aon: pinctrl@7d510700 { +- compatible = "brcm,bcm2712-aon-pinctrl"; +- reg = <0x7d510700 0x20>; +- +- i2c3_m4_agpio0_pins: i2c3_m4_agpio0_pins { +- function = "vc_i2c3"; +- pins = "aon_gpio0", "aon_gpio1"; +- bias-pull-up; +- }; +- +- bsc_m1_agpio13_pins: bsc_m1_agpio13_pins { +- function = "bsc_m1"; +- pins = "aon_gpio13", "aon_gpio14"; +- bias-pull-up; +- }; +- +- bsc_pmu_sgpio4_pins: bsc_pmu_sgpio4_pins { +- function = "avs_pmu_bsc"; +- pins = "aon_sgpio4", "aon_sgpio5"; +- }; +- +- bsc_m2_sgpio4_pins: bsc_m2_sgpio4_pins { +- function = "bsc_m2"; +- pins = "aon_sgpio4", "aon_sgpio5"; +- }; +- +- pwm_aon_agpio1_pins: pwm_aon_agpio1_pins { +- function = "aon_pwm"; +- pins = "aon_gpio1", "aon_gpio2"; +- }; +- +- pwm_aon_agpio4_pins: pwm_aon_agpio4_pins { +- function = "vc_pwm0"; +- pins = "aon_gpio4", "aon_gpio5"; +- }; +- +- pwm_aon_agpio7_pins: pwm_aon_agpio7_pins { +- function = "aon_pwm"; +- pins = "aon_gpio7", "aon_gpio9"; +- }; +- }; +- +- intc@7d517000 { +- compatible = "brcm,bcm7271-l2-intc"; +- reg = <0x7d517000 0x10>; +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <1>; +- status = "disabled"; +- }; +- +- bscc: i2c@7d517a00 { +- compatible = "brcm,brcmstb-i2c"; +- reg = <0x7d517a00 0x58>; +- interrupt-parent = <&bsc_aon_irq>; +- interrupts = <0>; +- clock-frequency = <200000>; +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- pwm_aon: pwm@7d517a80 { +- compatible = "brcm,bcm7038-pwm"; +- reg = <0x7d517a80 0x28>; +- #pwm-cells = <3>; +- clocks = <&clk_27MHz>; +- }; +- +- main_aon_irq: intc@7d517ac0 { +- compatible = "brcm,bcm7271-l2-intc"; +- reg = <0x7d517ac0 0x10>; +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <1>; +- }; +- +- bsc_aon_irq: intc@7d517b00 { +- compatible = "brcm,bcm7271-l2-intc"; +- reg = <0x7d517b00 0x10>; +- interrupts = ; +- interrupt-controller; +- #interrupt-cells = <1>; +- }; +- +- gio_aon: gpio@7d517c00 { +- compatible = "brcm,brcmstb-gpio"; +- reg = <0x7d517c00 0x40>; +- interrupt-parent = <&main_aon_irq>; +- interrupts = <0>; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- brcm,gpio-bank-widths = <17 6>; +- brcm,gpio-direct; +- }; +- +- avs_monitor: avs-monitor@7d542000 { +- compatible = "brcm,bcm2711-avs-monitor", +- "syscon", "simple-mfd"; +- reg = <0x7d542000 0xf00>; +- status = "okay"; +- +- thermal: thermal { +- compatible = "brcm,bcm2711-thermal"; +- #thermal-sensor-cells = <0>; +- }; +- }; +- +- bsc_pmu: i2c@7d544000 { +- compatible = "brcm,brcmstb-i2c"; +- reg = <0x7d544000 0x58>; +- interrupt-parent = <&bsc_aon_irq>; +- interrupts = <1>; +- clock-frequency = <200000>; +- status = "disabled"; +- }; +- +- hdmi0: hdmi@7ef00700 { +- compatible = "brcm,bcm2712-hdmi0"; +- reg = <0x7c701400 0x300>, +- <0x7c701000 0x200>, +- <0x7c701d00 0x300>, +- <0x7c702000 0x80>, +- <0x7c703800 0x200>, +- <0x7c704000 0x800>, +- <0x7c700100 0x80>, +- <0x7d510800 0x100>, +- <0x7c720000 0x100>; +- reg-names = "hdmi", +- "dvp", +- "phy", +- "rm", +- "packet", +- "metadata", +- "csc", +- "cec", +- "hd"; +- resets = <&dvp 1>; +- interrupt-parent = <&aon_intr>; +- interrupts = <1>, <2>, <3>, +- <7>, <8>; +- interrupt-names = "cec-tx", "cec-rx", "cec-low", +- "hpd-connected", "hpd-removed"; +- ddc = <&ddc0>; +- dmas = <&dma32 10>; +- dma-names = "audio-rx"; +- status = "disabled"; +- }; +- +- hdmi1: hdmi@7ef05700 { +- compatible = "brcm,bcm2712-hdmi1"; +- reg = <0x7c706400 0x300>, +- <0x7c706000 0x200>, +- <0x7c706d00 0x300>, +- <0x7c707000 0x80>, +- <0x7c708800 0x200>, +- <0x7c709000 0x800>, +- <0x7c700180 0x80>, +- <0x7d511000 0x100>, +- <0x7c720000 0x100>; +- reg-names = "hdmi", +- "dvp", +- "phy", +- "rm", +- "packet", +- "metadata", +- "csc", +- "cec", +- "hd"; +- ddc = <&ddc1>; +- resets = <&dvp 2>; +- interrupt-parent = <&aon_intr>; +- interrupts = <11>, <12>, <13>, +- <14>, <15>; +- interrupt-names = "cec-tx", "cec-rx", "cec-low", +- "hpd-connected", "hpd-removed"; +- dmas = <&dma32 17>; +- dma-names = "audio-rx"; +- status = "disabled"; +- }; +- }; +- +- arm-pmu { +- compatible = "arm,cortex-a76-pmu"; +- interrupts = , +- , +- , +- ; +- interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; +- }; +- +- timer { +- compatible = "arm,armv8-timer"; +- interrupts = , +- , +- , +- ; +- /* This only applies to the ARMv7 stub */ +- arm,cpu-registers-not-fw-configured; +- }; +- +- cpus: cpus { +- #address-cells = <1>; +- #size-cells = <0>; +- enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit +- +- /* Source for d/i cache-line-size, cache-sets, cache-size +- * https://developer.arm.com/documentation/100798/0401 +- * /L1-memory-system/About-the-L1-memory-system?lang=en +- */ +- cpu0: cpu@0 { +- device_type = "cpu"; +- compatible = "arm,cortex-a76"; +- reg = <0x000>; +- enable-method = "psci"; +- d-cache-size = <0x10000>; +- d-cache-line-size = <64>; +- d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set +- i-cache-size = <0x10000>; +- i-cache-line-size = <64>; +- i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set +- next-level-cache = <&l2_cache_l0>; +- }; +- +- cpu1: cpu@1 { +- device_type = "cpu"; +- compatible = "arm,cortex-a76"; +- reg = <0x100>; +- enable-method = "psci"; +- d-cache-size = <0x10000>; +- d-cache-line-size = <64>; +- d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set +- i-cache-size = <0x10000>; +- i-cache-line-size = <64>; +- i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set +- next-level-cache = <&l2_cache_l1>; +- }; +- +- cpu2: cpu@2 { +- device_type = "cpu"; +- compatible = "arm,cortex-a76"; +- reg = <0x200>; +- enable-method = "psci"; +- d-cache-size = <0x10000>; +- d-cache-line-size = <64>; +- d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set +- i-cache-size = <0x10000>; +- i-cache-line-size = <64>; +- i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set +- next-level-cache = <&l2_cache_l2>; +- }; +- +- cpu3: cpu@3 { +- device_type = "cpu"; +- compatible = "arm,cortex-a76"; +- reg = <0x300>; +- enable-method = "psci"; +- d-cache-size = <0x10000>; +- d-cache-line-size = <64>; +- d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set +- i-cache-size = <0x10000>; +- i-cache-line-size = <64>; +- i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set +- next-level-cache = <&l2_cache_l3>; +- }; +- +- /* Source for cache-line-size and cache-sets: +- * https://developer.arm.com/documentation/100798/0401 +- * /L2-memory-system/About-the-L2-memory-system?lang=en +- * and for cache-size: +- * https://www.raspberrypi.com/documentation/computers +- * /processors.html#bcm2712 +- */ +- l2_cache_l0: l2-cache-l0 { +- compatible = "cache"; +- cache-size = <0x80000>; +- cache-line-size = <128>; +- cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set +- cache-level = <2>; +- cache-unified; +- next-level-cache = <&l3_cache>; +- }; +- +- l2_cache_l1: l2-cache-l1 { +- compatible = "cache"; +- cache-size = <0x80000>; +- cache-line-size = <128>; +- cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set +- cache-level = <2>; +- cache-unified; +- next-level-cache = <&l3_cache>; +- }; +- +- l2_cache_l2: l2-cache-l2 { +- compatible = "cache"; +- cache-size = <0x80000>; +- cache-line-size = <128>; +- cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set +- cache-level = <2>; +- cache-unified; +- next-level-cache = <&l3_cache>; +- }; +- +- l2_cache_l3: l2-cache-l3 { +- compatible = "cache"; +- cache-size = <0x80000>; +- cache-line-size = <128>; +- cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set +- cache-level = <2>; +- cache-unified; +- next-level-cache = <&l3_cache>; +- }; +- +- /* Source for cache-line-size and cache-sets: +- * https://developer.arm.com/documentation/100453/0401/L3-cache?lang=en +- * Source for cache-size: +- * https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712 +- */ +- l3_cache: l3-cache { +- compatible = "cache"; +- cache-size = <0x200000>; +- cache-line-size = <64>; +- cache-sets = <2048>; // 2MiB(size)/64(line-size)=32768ways/16-way set +- cache-level = <3>; +- }; +- }; +- +- psci { +- method = "smc"; +- compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; +- cpu_on = <0xc4000003>; +- cpu_suspend = <0xc4000001>; +- cpu_off = <0x84000002>; +- }; +- +- axi: axi { +- compatible = "simple-bus"; +- #address-cells = <2>; +- #size-cells = <2>; +- +- ranges = <0x00 0x00000000 0x00 0x00000000 0x10 0x00000000>, +- <0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>, +- <0x14 0x00000000 0x14 0x00000000 0x04 0x00000000>, +- <0x18 0x00000000 0x18 0x00000000 0x04 0x00000000>, +- <0x1c 0x00000000 0x1c 0x00000000 0x04 0x00000000>; +- +- dma-ranges = <0x00 0x00000000 0x00 0x00000000 0x10 0x00000000>, +- <0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>, +- <0x14 0x00000000 0x14 0x00000000 0x04 0x00000000>, +- <0x18 0x00000000 0x18 0x00000000 0x04 0x00000000>, +- <0x1c 0x00000000 0x1c 0x00000000 0x04 0x00000000>; +- +- vc4: gpu { +- compatible = "brcm,bcm2712-vc6"; +- }; +- +- iommu2: iommu@5100 { +- /* IOMMU2 for PISP-BE, HEVC; and (unused) H264 accelerators */ +- compatible = "brcm,bcm2712-iommu"; +- reg = <0x10 0x5100 0x0 0x80>; +- cache = <&iommuc>; +- #iommu-cells = <0>; +- }; +- +- iommu4: iommu@5200 { +- /* IOMMU4 for HVS, MPL/TXP; and (unused) Unicam, PISP-FE, MiniBVN */ +- compatible = "brcm,bcm2712-iommu"; +- reg = <0x10 0x5200 0x0 0x80>; +- cache = <&iommuc>; +- #iommu-cells = <0>; +- #interconnect-cells = <0>; +- }; +- +- iommu5: iommu@5280 { +- /* IOMMU5 for PCIe2 (RP1); and (unused) BSTM */ +- compatible = "brcm,bcm2712-iommu"; +- reg = <0x10 0x5280 0x0 0x80>; +- cache = <&iommuc>; +- #iommu-cells = <0>; +- dma-iova-offset = <0x10 0x00000000>; // HACK for RP1 masters over PCIe +- }; +- +- iommuc: iommuc@5b00 { +- compatible = "brcm,bcm2712-iommuc"; +- reg = <0x10 0x5b00 0x0 0x80>; +- }; +- +- dma32: dma@10000 { +- compatible = "brcm,bcm2712-dma"; +- reg = <0x10 0x00010000 0 0x600>; +- interrupts = , +- , +- , +- , +- , +- ; +- interrupt-names = "dma0", +- "dma1", +- "dma2", +- "dma3", +- "dma4", +- "dma5"; +- #dma-cells = <1>; +- brcm,dma-channel-mask = <0x0035>; +- }; +- +- dma40: dma@10600 { +- compatible = "brcm,bcm2712-dma"; +- reg = <0x10 0x00010600 0 0x600>; +- interrupts = +- , /* dma4 6 */ +- , /* dma4 7 */ +- , /* dma4 8 */ +- , /* dma4 9 */ +- , /* dma4 10 */ +- ; /* dma4 11 */ +- interrupt-names = "dma6", +- "dma7", +- "dma8", +- "dma9", +- "dma10", +- "dma11"; +- #dma-cells = <1>; +- brcm,dma-channel-mask = <0x0fc0>; +- }; +- +- // Single-lane Gen3 PCIe +- // Outbound window at 0x14_000000-0x17_ffffff +- pcie0: pcie@100000 { +- compatible = "brcm,bcm2712-pcie"; +- reg = <0x10 0x00100000 0x0 0x9310>; +- device_type = "pci"; +- max-link-speed = <2>; +- #address-cells = <3>; +- #interrupt-cells = <1>; +- #size-cells = <2>; +- /* +- * Unused interrupts: +- * 208: AER +- * 215: NMI +- * 216: PME +- */ +- interrupt-parent = <&gicv2>; +- interrupts = , +- ; +- interrupt-names = "pcie", "msi"; +- interrupt-map-mask = <0x0 0x0 0x0 0x7>; +- interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 209 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 2 &gicv2 GIC_SPI 210 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 3 &gicv2 GIC_SPI 211 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 4 &gicv2 GIC_SPI 212 +- IRQ_TYPE_LEVEL_HIGH>; +- resets = <&bcm_reset 5>, <&bcm_reset 42>, <&pcie_rescal>; +- reset-names = "swinit", "bridge", "rescal"; +- msi-controller; +- msi-parent = <&pcie0>; +- +- ranges = <0x02000000 0x00 0x00000000 +- 0x17 0x00000000 +- 0x0 0xfffffffc>, +- <0x43000000 0x04 0x00000000 +- 0x14 0x00000000 +- 0x3 0x00000000>; +- +- dma-ranges = <0x43000000 0x10 0x00000000 +- 0x00 0x00000000 +- 0x10 0x00000000>; +- +- status = "disabled"; +- }; +- +- // Single-lane Gen3 PCIe +- // Outbound window at 0x18_000000-0x1b_ffffff +- pcie1: pcie@110000 { +- compatible = "brcm,bcm2712-pcie"; +- reg = <0x10 0x00110000 0x0 0x9310>; +- device_type = "pci"; +- max-link-speed = <2>; +- #address-cells = <3>; +- #interrupt-cells = <1>; +- #size-cells = <2>; +- /* +- * Unused interrupts: +- * 218: AER +- * 225: NMI +- * 226: PME +- */ +- interrupt-parent = <&gicv2>; +- interrupts = , +- ; +- interrupt-names = "pcie", "msi"; +- interrupt-map-mask = <0x0 0x0 0x0 0x7>; +- interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 219 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 2 &gicv2 GIC_SPI 220 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 3 &gicv2 GIC_SPI 221 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 4 &gicv2 GIC_SPI 222 +- IRQ_TYPE_LEVEL_HIGH>; +- resets = <&bcm_reset 7>, <&bcm_reset 43>, <&pcie_rescal>; +- reset-names = "swinit", "bridge", "rescal"; +- msi-controller; +- msi-parent = <&mip1>; +- +- ranges = <0x02000000 0x00 0x00000000 +- 0x1b 0x00000000 +- 0x00 0xfffffffc>, +- <0x43000000 0x04 0x00000000 +- 0x18 0x00000000 +- 0x03 0x00000000>; +- +- dma-ranges = <0x03000000 0x10 0x00000000 +- 0x00 0x00000000 +- 0x10 0x00000000>; +- +- status = "disabled"; +- }; +- +- pcie_rescal: reset-controller@119500 { +- compatible = "brcm,bcm7216-pcie-sata-rescal"; +- reg = <0x10 0x00119500 0x0 0x10>; +- #reset-cells = <0>; +- }; +- +- // Quad-lane Gen3 PCIe +- // Outbound window at 0x1c_000000-0x1f_ffffff +- pcie2: pcie@120000 { +- compatible = "brcm,bcm2712-pcie"; +- reg = <0x10 0x00120000 0x0 0x9310>; +- device_type = "pci"; +- max-link-speed = <2>; +- #address-cells = <3>; +- #interrupt-cells = <1>; +- #size-cells = <2>; +- /* +- * Unused interrupts: +- * 228: AER +- * 235: NMI +- * 236: PME +- */ +- interrupt-parent = <&gicv2>; +- interrupts = , +- ; +- interrupt-names = "pcie", "msi"; +- interrupt-map-mask = <0x0 0x0 0x0 0x7>; +- interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 229 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 2 &gicv2 GIC_SPI 230 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 3 &gicv2 GIC_SPI 231 +- IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 4 &gicv2 GIC_SPI 232 +- IRQ_TYPE_LEVEL_HIGH>; +- resets = <&bcm_reset 32>, <&bcm_reset 44>, <&pcie_rescal>; +- reset-names = "swinit", "bridge", "rescal"; +- msi-controller; +- msi-parent = <&mip0>; +- +- // ~4GB, 32-bit, not-prefetchable at PCIe 00_00000000 +- ranges = <0x02000000 0x00 0x00000000 +- 0x1f 0x00000000 +- 0x0 0xfffffffc>, +- // 12GB, 64-bit, prefetchable at PCIe 04_00000000 +- <0x43000000 0x04 0x00000000 +- 0x1c 0x00000000 +- 0x03 0x00000000>; +- +- // 64GB system RAM space at PCIe 10_00000000 +- dma-ranges = <0x02000000 0x00 0x00000000 +- 0x1f 0x00000000 +- 0x00 0x00400000>, +- <0x43000000 0x10 0x00000000 +- 0x00 0x00000000 +- 0x10 0x00000000>; +- +- status = "disabled"; +- }; +- +- mip0: msi-controller@130000 { +- compatible = "brcm,bcm2712-mip-intc"; +- reg = <0x10 0x00130000 0x0 0xc0>; +- msi-controller; +- interrupt-controller; +- #interrupt-cells = <2>; +- brcm,msi-base-spi = <128>; +- brcm,msi-num-spis = <64>; +- brcm,msi-offset = <0>; +- brcm,msi-pci-addr = <0xff 0xfffff000>; +- }; +- +- mip1: msi-controller@131000 { +- compatible = "brcm,bcm2712-mip-intc"; +- reg = <0x10 0x00131000 0x0 0xc0>; +- msi-controller; +- interrupt-controller; +- #interrupt-cells = <2>; +- brcm,msi-base-spi = <247>; +- /* Actually 20 total, but the others are +- * both sparse and non-consecutive */ +- brcm,msi-num-spis = <8>; +- brcm,msi-offset = <8>; +- brcm,msi-pci-addr = <0xff 0xffffe000>; +- }; +- +- syscon_piarbctl: syscon@400018 { +- compatible = "brcm,syscon-piarbctl", "syscon", "simple-mfd"; +- reg = <0x10 0x00400018 0x0 0x18>; +- }; +- +- usb: usb@480000 { +- compatible = "brcm,bcm2835-usb"; +- reg = <0x10 0x00480000 0x0 0x10000>; +- interrupts = ; +- #address-cells = <1>; +- #size-cells = <0>; +- clocks = <&clk_usb>; +- clock-names = "otg"; +- phys = <&usbphy>; +- phy-names = "usb2-phy"; +- status = "disabled"; +- }; +- +- rpivid: codec@800000 { +- compatible = "raspberrypi,rpivid-vid-decoder"; +- reg = <0x10 0x00800000 0x0 0x10000>, /* HEVC */ +- <0x10 0x00840000 0x0 0x1000>; /* INTC */ +- reg-names = "hevc", +- "intc"; +- +- interrupts = ; +- +- clocks = <&firmware_clocks 11>; +- clock-names = "hevc"; +- iommus = <&iommu2>; +- status = "disabled"; +- }; +- +- sdio1: mmc@fff000 { +- compatible = "brcm,bcm2712-sdhci"; +- reg = <0x10 0x00fff000 0x0 0x260>, +- <0x10 0x00fff400 0x0 0x200>, +- <0x10 0x015040b0 0x0 0x4>, // Bus isolation control +- <0x10 0x015200f0 0x0 0x24>; // LCPLL control misc0-8 +- reg-names = "host", "cfg", "busisol", "lcpll"; +- interrupts = ; +- clocks = <&clk_emmc2>; +- sdhci-caps-mask = <0x0000C000 0x0>; +- sdhci-caps = <0x0 0x0>; +- mmc-ddr-3_3v; +- }; +- +- sdio2: mmc@1100000 { +- compatible = "brcm,bcm2712-sdhci"; +- reg = <0x10 0x01100000 0x0 0x260>, +- <0x10 0x01100400 0x0 0x200>; +- reg-names = "host", "cfg"; +- interrupts = ; +- clocks = <&clk_emmc2>; +- sdhci-caps-mask = <0x0000C000 0x0>; +- sdhci-caps = <0x0 0x0>; +- supports-cqe; +- mmc-ddr-3_3v; +- status = "disabled"; +- }; +- +- bcm_reset: reset-controller@1504318 { +- compatible = "brcm,brcmstb-reset"; +- reg = <0x10 0x01504318 0x0 0x30>; +- #reset-cells = <1>; +- }; +- +- v3d: v3d@2000000 { +- compatible = "brcm,2712-v3d"; +- reg = <0x10 0x02000000 0x0 0x4000>, +- <0x10 0x02008000 0x0 0x6000>; +- reg-names = "hub", "core0"; +- +- power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>; +- resets = <&pm BCM2835_RESET_V3D>; +- clocks = <&firmware_clocks 5>; +- clocks-names = "v3d"; +- interrupts = , +- ; +- status = "disabled"; +- }; +- +- gicv2: interrupt-controller@7fff9000 { +- interrupt-controller; +- #interrupt-cells = <3>; +- compatible = "arm,gic-400"; +- reg = <0x10 0x7fff9000 0x0 0x1000>, +- <0x10 0x7fffa000 0x0 0x2000>, +- <0x10 0x7fffc000 0x0 0x2000>, +- <0x10 0x7fffe000 0x0 0x2000>; +- interrupts = ; +- }; +- +- pisp_be: pisp_be@880000 { +- compatible = "raspberrypi,pispbe"; +- reg = <0x10 0x00880000 0x0 0x4000>; +- interrupts = ; +- clocks = <&firmware_clocks 7>; +- clocks-names = "isp_be"; +- status = "okay"; +- iommus = <&iommu2>; +- }; +- }; +- +- clocks { +- /* The oscillator is the root of the clock tree. */ +- clk_osc: clk-osc { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "osc"; +- clock-frequency = <54000000>; +- }; +- +- clk_usb: clk-usb { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "otg"; +- clock-frequency = <480000000>; +- }; +- +- clk_vpu: clk_vpu { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <750000000>; +- clock-output-names = "vpu-clock"; +- }; +- +- clk_uart: clk_uart { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <9216000>; +- clock-output-names = "uart-clock"; +- }; +- +- clk_emmc2: clk_emmc2 { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <200000000>; +- clock-output-names = "emmc2-clock"; +- }; +- }; +- +- usbphy: phy { +- compatible = "usb-nop-xceiv"; +- #phy-cells = <0>; +- }; +-}; +--- a/arch/arm/boot/dts/broadcom/rp1.dtsi ++++ /dev/null +@@ -1,1287 +0,0 @@ +-#include +-#include +-#include +- +-&rp1_target { +- rp1: rp1 { +- compatible = "simple-bus"; +- #address-cells = <2>; +- #size-cells = <2>; +- #interrupt-cells = <2>; +- interrupt-controller; +- interrupt-parent = <&rp1>; +- +- // ranges and dma-ranges must be provided by the includer +- +- rp1_clocks: clocks@18000 { +- compatible = "raspberrypi,rp1-clocks"; +- #clock-cells = <1>; +- reg = <0xc0 0x40018000 0x0 0x10038>; +- clocks = <&clk_xosc>; +- +- assigned-clocks = <&rp1_clocks RP1_PLL_SYS_CORE>, +- <&rp1_clocks RP1_PLL_AUDIO_CORE>, +- // RP1_PLL_VIDEO_CORE and dividers are now managed by VEC,DPI drivers +- <&rp1_clocks RP1_PLL_SYS>, +- <&rp1_clocks RP1_PLL_SYS_SEC>, +- <&rp1_clocks RP1_PLL_AUDIO>, +- <&rp1_clocks RP1_PLL_AUDIO_SEC>, +- <&rp1_clocks RP1_CLK_SYS>, +- <&rp1_clocks RP1_PLL_SYS_PRI_PH>, +- // RP1_CLK_SLOW_SYS is used for the frequency counter (FC0) +- <&rp1_clocks RP1_CLK_SLOW_SYS>, +- <&rp1_clocks RP1_CLK_SDIO_TIMER>, +- <&rp1_clocks RP1_CLK_SDIO_ALT_SRC>, +- <&rp1_clocks RP1_CLK_ETH_TSU>; +- +- assigned-clock-rates = <1000000000>, // RP1_PLL_SYS_CORE +- <1536000000>, // RP1_PLL_AUDIO_CORE +- <200000000>, // RP1_PLL_SYS +- <125000000>, // RP1_PLL_SYS_SEC +- <61440000>, // RP1_PLL_AUDIO +- <192000000>, // RP1_PLL_AUDIO_SEC +- <200000000>, // RP1_CLK_SYS +- <100000000>, // RP1_PLL_SYS_PRI_PH +- // Must match the XOSC frequency +- <50000000>, // RP1_CLK_SLOW_SYS +- <1000000>, // RP1_CLK_SDIO_TIMER +- <200000000>, // RP1_CLK_SDIO_ALT_SRC +- <50000000>; // RP1_CLK_ETH_TSU +- }; +- +- rp1_uart0: serial@30000 { +- compatible = "arm,pl011-axi"; +- reg = <0xc0 0x40030000 0x0 0x100>; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; +- clock-names = "uartclk", "apb_pclk"; +- dmas = <&rp1_dma RP1_DMA_UART0_TX>, +- <&rp1_dma RP1_DMA_UART0_RX>; +- dma-names = "tx", "rx"; +- pinctrl-names = "default"; +- arm,primecell-periphid = <0x00541011>; +- uart-has-rtscts; +- cts-event-workaround; +- skip-init; +- status = "disabled"; +- }; +- +- rp1_uart1: serial@34000 { +- compatible = "arm,pl011-axi"; +- reg = <0xc0 0x40034000 0x0 0x100>; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; +- clock-names = "uartclk", "apb_pclk"; +- // dmas = <&rp1_dma RP1_DMA_UART1_TX>, +- // <&rp1_dma RP1_DMA_UART1_RX>; +- // dma-names = "tx", "rx"; +- pinctrl-names = "default"; +- arm,primecell-periphid = <0x00541011>; +- uart-has-rtscts; +- cts-event-workaround; +- skip-init; +- status = "disabled"; +- }; +- +- rp1_uart2: serial@38000 { +- compatible = "arm,pl011-axi"; +- reg = <0xc0 0x40038000 0x0 0x100>; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; +- clock-names = "uartclk", "apb_pclk"; +- // dmas = <&rp1_dma RP1_DMA_UART2_TX>, +- // <&rp1_dma RP1_DMA_UART2_RX>; +- // dma-names = "tx", "rx"; +- pinctrl-names = "default"; +- arm,primecell-periphid = <0x00541011>; +- uart-has-rtscts; +- cts-event-workaround; +- skip-init; +- status = "disabled"; +- }; +- +- rp1_uart3: serial@3c000 { +- compatible = "arm,pl011-axi"; +- reg = <0xc0 0x4003c000 0x0 0x100>; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; +- clock-names = "uartclk", "apb_pclk"; +- // dmas = <&rp1_dma RP1_DMA_UART3_TX>, +- // <&rp1_dma RP1_DMA_UART3_RX>; +- // dma-names = "tx", "rx"; +- pinctrl-names = "default"; +- arm,primecell-periphid = <0x00541011>; +- uart-has-rtscts; +- cts-event-workaround; +- skip-init; +- status = "disabled"; +- }; +- +- rp1_uart4: serial@40000 { +- compatible = "arm,pl011-axi"; +- reg = <0xc0 0x40040000 0x0 0x100>; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; +- clock-names = "uartclk", "apb_pclk"; +- // dmas = <&rp1_dma RP1_DMA_UART4_TX>, +- // <&rp1_dma RP1_DMA_UART4_RX>; +- // dma-names = "tx", "rx"; +- pinctrl-names = "default"; +- arm,primecell-periphid = <0x00541011>; +- uart-has-rtscts; +- cts-event-workaround; +- skip-init; +- status = "disabled"; +- }; +- +- rp1_uart5: serial@44000 { +- compatible = "arm,pl011-axi"; +- reg = <0xc0 0x40044000 0x0 0x100>; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; +- clock-names = "uartclk", "apb_pclk"; +- // dmas = <&rp1_dma RP1_DMA_UART5_TX>, +- // <&rp1_dma RP1_DMA_UART5_RX>; +- // dma-names = "tx", "rx"; +- pinctrl-names = "default"; +- arm,primecell-periphid = <0x00541011>; +- uart-has-rtscts; +- cts-event-workaround; +- skip-init; +- status = "disabled"; +- }; +- +- rp1_spi8: spi@4c000 { +- reg = <0xc0 0x4004c000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <1>; +- #size-cells = <0>; +- num-cs = <2>; +- dmas = <&rp1_dma RP1_DMA_SPI8_TX>, +- <&rp1_dma RP1_DMA_SPI8_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- rp1_spi0: spi@50000 { +- reg = <0xc0 0x40050000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <1>; +- #size-cells = <0>; +- num-cs = <2>; +- dmas = <&rp1_dma RP1_DMA_SPI0_TX>, +- <&rp1_dma RP1_DMA_SPI0_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- rp1_spi1: spi@54000 { +- reg = <0xc0 0x40054000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <1>; +- #size-cells = <0>; +- num-cs = <2>; +- dmas = <&rp1_dma RP1_DMA_SPI1_TX>, +- <&rp1_dma RP1_DMA_SPI1_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- rp1_spi2: spi@58000 { +- reg = <0xc0 0x40058000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <1>; +- #size-cells = <0>; +- num-cs = <2>; +- dmas = <&rp1_dma RP1_DMA_SPI2_TX>, +- <&rp1_dma RP1_DMA_SPI2_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- rp1_spi3: spi@5c000 { +- reg = <0xc0 0x4005c000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <1>; +- #size-cells = <0>; +- num-cs = <2>; +- dmas = <&rp1_dma RP1_DMA_SPI3_TX>, +- <&rp1_dma RP1_DMA_SPI3_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- // SPI4 is a target/slave interface +- rp1_spi4: spi@60000 { +- reg = <0xc0 0x40060000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <0>; +- #size-cells = <0>; +- num-cs = <1>; +- spi-slave; +- dmas = <&rp1_dma RP1_DMA_SPI4_TX>, +- <&rp1_dma RP1_DMA_SPI4_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- +- slave { +- compatible = "spidev"; +- spi-max-frequency = <1000000>; +- }; +- }; +- +- rp1_spi5: spi@64000 { +- reg = <0xc0 0x40064000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <1>; +- #size-cells = <0>; +- num-cs = <2>; +- dmas = <&rp1_dma RP1_DMA_SPI5_TX>, +- <&rp1_dma RP1_DMA_SPI5_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- rp1_spi6: spi@68000 { +- reg = <0xc0 0x40068000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <1>; +- #size-cells = <0>; +- num-cs = <2>; +- dmas = <&rp1_dma RP1_DMA_SPI6_TX>, +- <&rp1_dma RP1_DMA_SPI6_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- // SPI7 is a target/slave interface +- rp1_spi7: spi@6c000 { +- reg = <0xc0 0x4006c000 0x0 0x130>; +- compatible = "snps,dw-apb-ssi"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- clock-names = "ssi_clk"; +- #address-cells = <0>; +- #size-cells = <0>; +- num-cs = <1>; +- spi-slave; +- dmas = <&rp1_dma RP1_DMA_SPI7_TX>, +- <&rp1_dma RP1_DMA_SPI7_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- +- slave { +- compatible = "spidev"; +- spi-max-frequency = <1000000>; +- }; +- }; +- +- rp1_i2c0: i2c@70000 { +- reg = <0xc0 0x40070000 0x0 0x1000>; +- compatible = "snps,designware-i2c"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- i2c-scl-rising-time-ns = <65>; +- i2c-scl-falling-time-ns = <100>; +- status = "disabled"; +- }; +- +- rp1_i2c1: i2c@74000 { +- reg = <0xc0 0x40074000 0x0 0x1000>; +- compatible = "snps,designware-i2c"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- i2c-scl-rising-time-ns = <65>; +- i2c-scl-falling-time-ns = <100>; +- status = "disabled"; +- }; +- +- rp1_i2c2: i2c@78000 { +- reg = <0xc0 0x40078000 0x0 0x1000>; +- compatible = "snps,designware-i2c"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- i2c-scl-rising-time-ns = <65>; +- i2c-scl-falling-time-ns = <100>; +- status = "disabled"; +- }; +- +- rp1_i2c3: i2c@7c000 { +- reg = <0xc0 0x4007c000 0x0 0x1000>; +- compatible = "snps,designware-i2c"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- i2c-scl-rising-time-ns = <65>; +- i2c-scl-falling-time-ns = <100>; +- status = "disabled"; +- }; +- +- rp1_i2c4: i2c@80000 { +- reg = <0xc0 0x40080000 0x0 0x1000>; +- compatible = "snps,designware-i2c"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- i2c-scl-rising-time-ns = <65>; +- i2c-scl-falling-time-ns = <100>; +- status = "disabled"; +- }; +- +- rp1_i2c5: i2c@84000 { +- reg = <0xc0 0x40084000 0x0 0x1000>; +- compatible = "snps,designware-i2c"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- i2c-scl-rising-time-ns = <65>; +- i2c-scl-falling-time-ns = <100>; +- status = "disabled"; +- }; +- +- rp1_i2c6: i2c@88000 { +- reg = <0xc0 0x40088000 0x0 0x1000>; +- compatible = "snps,designware-i2c"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS>; +- i2c-scl-rising-time-ns = <65>; +- i2c-scl-falling-time-ns = <100>; +- status = "disabled"; +- }; +- +- rp1_pwm0: pwm@98000 { +- compatible = "raspberrypi,rp1-pwm"; +- reg = <0xc0 0x40098000 0x0 0x100>; +- #pwm-cells = <3>; +- clocks = <&rp1_clocks RP1_CLK_PWM0>; +- assigned-clocks = <&rp1_clocks RP1_CLK_PWM0>; +- assigned-clock-rates = <50000000>; +- status = "disabled"; +- }; +- +- rp1_pwm1: pwm@9c000 { +- compatible = "raspberrypi,rp1-pwm"; +- reg = <0xc0 0x4009c000 0x0 0x100>; +- #pwm-cells = <3>; +- clocks = <&rp1_clocks RP1_CLK_PWM1>; +- assigned-clocks = <&rp1_clocks RP1_CLK_PWM1>; +- assigned-clock-rates = <50000000>; +- status = "disabled"; +- }; +- +- rp1_i2s0: i2s@a0000 { +- reg = <0xc0 0x400a0000 0x0 0x1000>; +- compatible = "snps,designware-i2s"; +- // Providing an interrupt disables DMA +- // interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_I2S>; +- clock-names = "i2sclk"; +- #sound-dai-cells = <0>; +- dmas = <&rp1_dma RP1_DMA_I2S0_TX>,<&rp1_dma RP1_DMA_I2S0_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- rp1_i2s1: i2s@a4000 { +- reg = <0xc0 0x400a4000 0x0 0x1000>; +- compatible = "snps,designware-i2s"; +- // Providing an interrupt disables DMA +- // interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_I2S>; +- clock-names = "i2sclk"; +- #sound-dai-cells = <0>; +- dmas = <&rp1_dma RP1_DMA_I2S1_TX>,<&rp1_dma RP1_DMA_I2S1_RX>; +- dma-names = "tx", "rx"; +- status = "disabled"; +- }; +- +- rp1_i2s2: i2s@a8000 { +- reg = <0xc0 0x400a8000 0x0 0x1000>; +- compatible = "snps,designware-i2s"; +- // Providing an interrupt disables DMA +- // interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_I2S>; +- status = "disabled"; +- }; +- +- rp1_sdio_clk0: sdio_clk0@b0004 { +- compatible = "raspberrypi,rp1-sdio-clk"; +- reg = <0xc0 0x400b0004 0x0 0x1c>; +- clocks = <&sdio_src &sdhci_core>; +- clock-names = "src", "base"; +- #clock-cells = <0>; +- status = "disabled"; +- }; +- +- rp1_sdio_clk1: sdio_clk1@b4004 { +- compatible = "raspberrypi,rp1-sdio-clk"; +- reg = <0xc0 0x400b4004 0x0 0x1c>; +- clocks = <&sdio_src &sdhci_core>; +- clock-names = "src", "base"; +- #clock-cells = <0>; +- status = "disabled"; +- }; +- +- rp1_adc: adc@c8000 { +- compatible = "raspberrypi,rp1-adc"; +- reg = <0xc0 0x400c8000 0x0 0x4000>; +- clocks = <&rp1_clocks RP1_CLK_ADC>; +- clock-names = "adcclk"; +- #clock-cells = <0>; +- vref-supply = <&rp1_vdd_3v3>; +- status = "disabled"; +- }; +- +- rp1_gpio: gpio@d0000 { +- reg = <0xc0 0x400d0000 0x0 0xc000>, +- <0xc0 0x400e0000 0x0 0xc000>, +- <0xc0 0x400f0000 0x0 0xc000>; +- compatible = "raspberrypi,rp1-gpio"; +- interrupts = , +- , +- ; +- gpio-controller; +- #gpio-cells = <2>; +- interrupt-controller; +- #interrupt-cells = <2>; +- gpio-ranges = <&rp1_gpio 0 0 54>; +- +- rp1_uart0_14_15: rp1_uart0_14_15 { +- pin_txd { +- function = "uart0"; +- pins = "gpio14"; +- bias-disable; +- }; +- pin_rxd { +- function = "uart0"; +- pins = "gpio15"; +- bias-pull-up; +- }; +- }; +- rp1_uart0_ctsrts_16_17: rp1_uart0_ctsrts_16_17 { +- pin_cts { +- function = "uart0"; +- pins = "gpio16"; +- bias-pull-up; +- }; +- pin_rts { +- function = "uart0"; +- pins = "gpio17"; +- bias-disable; +- }; +- }; +- rp1_uart1_0_1: rp1_uart1_0_1 { +- pin_txd { +- function = "uart1"; +- pins = "gpio0"; +- bias-disable; +- }; +- pin_rxd { +- function = "uart1"; +- pins = "gpio1"; +- bias-pull-up; +- }; +- }; +- rp1_uart1_ctsrts_2_3: rp1_uart1_ctsrts_2_3 { +- pin_cts { +- function = "uart1"; +- pins = "gpio2"; +- bias-pull-up; +- }; +- pin_rts { +- function = "uart1"; +- pins = "gpio3"; +- bias-disable; +- }; +- }; +- rp1_uart2_4_5: rp1_uart2_4_5 { +- pin_txd { +- function = "uart2"; +- pins = "gpio4"; +- bias-disable; +- }; +- pin_rxd { +- function = "uart2"; +- pins = "gpio5"; +- bias-pull-up; +- }; +- }; +- rp1_uart2_ctsrts_6_7: rp1_uart2_ctsrts_6_7 { +- pin_cts { +- function = "uart2"; +- pins = "gpio6"; +- bias-pull-up; +- }; +- pin_rts { +- function = "uart2"; +- pins = "gpio7"; +- bias-disable; +- }; +- }; +- rp1_uart3_8_9: rp1_uart3_8_9 { +- pin_txd { +- function = "uart3"; +- pins = "gpio8"; +- bias-disable; +- }; +- pin_rxd { +- function = "uart3"; +- pins = "gpio9"; +- bias-pull-up; +- }; +- }; +- rp1_uart3_ctsrts_10_11: rp1_uart3_ctsrts_10_11 { +- pin_cts { +- function = "uart3"; +- pins = "gpio10"; +- bias-pull-up; +- }; +- pin_rts { +- function = "uart3"; +- pins = "gpio11"; +- bias-disable; +- }; +- }; +- rp1_uart4_12_13: rp1_uart4_12_13 { +- pin_txd { +- function = "uart4"; +- pins = "gpio12"; +- bias-disable; +- }; +- pin_rxd { +- function = "uart4"; +- pins = "gpio13"; +- bias-pull-up; +- }; +- }; +- rp1_uart4_ctsrts_14_15: rp1_uart4_ctsrts_14_15 { +- pin_cts { +- function = "uart4"; +- pins = "gpio14"; +- bias-pull-up; +- }; +- pin_rts { +- function = "uart4"; +- pins = "gpio15"; +- bias-disable; +- }; +- }; +- +- rp1_sdio0_22_27: rp1_sdio0_22_27 { +- pin_clk { +- function = "sd0"; +- pins = "gpio22"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- pin_cmd { +- function = "sd0"; +- pins = "gpio23"; +- bias-pull-up; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- pins_dat { +- function = "sd0"; +- pins = "gpio24", "gpio25", "gpio26", "gpio27"; +- bias-pull-up; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- }; +- +- rp1_sdio1_28_33: rp1_sdio1_28_33 { +- pin_clk { +- function = "sd1"; +- pins = "gpio28"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- pin_cmd { +- function = "sd1"; +- pins = "gpio29"; +- bias-pull-up; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- pins_dat { +- function = "sd1"; +- pins = "gpio30", "gpio31", "gpio32", "gpio33"; +- bias-pull-up; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- }; +- +- rp1_i2s0_18_21: rp1_i2s0_18_21 { +- function = "i2s0"; +- pins = "gpio18", "gpio19", "gpio20", "gpio21"; +- bias-disable; +- }; +- +- rp1_i2s1_18_21: rp1_i2s1_18_21 { +- function = "i2s1"; +- pins = "gpio18", "gpio19", "gpio20", "gpio21"; +- bias-disable; +- }; +- +- rp1_i2c4_34_35: rp1_i2c4_34_35 { +- function = "i2c4"; +- pins = "gpio34", "gpio35"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c6_38_39: rp1_i2c6_38_39 { +- function = "i2c6"; +- pins = "gpio38", "gpio39"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c4_40_41: rp1_i2c4_40_41 { +- function = "i2c4"; +- pins = "gpio40", "gpio41"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c5_44_45: rp1_i2c5_44_45 { +- function = "i2c5"; +- pins = "gpio44", "gpio45"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c0_0_1: rp1_i2c0_0_1 { +- function = "i2c0"; +- pins = "gpio0", "gpio1"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c0_8_9: rp1_i2c0_8_9 { +- function = "i2c0"; +- pins = "gpio8", "gpio9"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c1_2_3: rp1_i2c1_2_3 { +- function = "i2c1"; +- pins = "gpio2", "gpio3"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c1_10_11: rp1_i2c1_10_11 { +- function = "i2c1"; +- pins = "gpio10", "gpio11"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c2_4_5: rp1_i2c2_4_5 { +- function = "i2c2"; +- pins = "gpio4", "gpio5"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c2_12_13: rp1_i2c2_12_13 { +- function = "i2c2"; +- pins = "gpio12", "gpio13"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c3_6_7: rp1_i2c3_6_7 { +- function = "i2c3"; +- pins = "gpio6", "gpio7"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c3_14_15: rp1_i2c3_14_15 { +- function = "i2c3"; +- pins = "gpio14", "gpio15"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- rp1_i2c3_22_23: rp1_i2c3_22_23 { +- function = "i2c3"; +- pins = "gpio22", "gpio23"; +- drive-strength = <12>; +- bias-pull-up; +- }; +- +- // DPI mappings with HSYNC,VSYNC but without PIXCLK,DE +- rp1_dpi_16bit_gpio2: rp1_dpi_16bit_gpio2 { /* Mode 2, not fully supported by RP1 */ +- function = "dpi"; +- pins = "gpio2", "gpio3", "gpio4", "gpio5", +- "gpio6", "gpio7", "gpio8", "gpio9", +- "gpio10", "gpio11", "gpio12", "gpio13", +- "gpio14", "gpio15", "gpio16", "gpio17", +- "gpio18", "gpio19"; +- bias-disable; +- }; +- rp1_dpi_16bit_cpadhi_gpio2: rp1_dpi_16bit_cpadhi_gpio2 { /* Mode 3 */ +- function = "dpi"; +- pins = "gpio2", "gpio3", "gpio4", "gpio5", +- "gpio6", "gpio7", "gpio8", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", +- "gpio20", "gpio21", "gpio22", "gpio23", +- "gpio24"; +- bias-disable; +- }; +- rp1_dpi_16bit_pad666_gpio2: rp1_dpi_16bit_pad666_gpio2 { /* Mode 4 */ +- function = "dpi"; +- pins = "gpio2", "gpio3", +- "gpio5", "gpio6", "gpio7", "gpio8", +- "gpio9", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", +- "gpio21", "gpio22", "gpio23", "gpio24", +- "gpio25"; +- bias-disable; +- }; +- rp1_dpi_18bit_gpio2: rp1_dpi_18bit_gpio2 { /* Mode 5, not fully supported by RP1 */ +- function = "dpi"; +- pins = "gpio2", "gpio3", "gpio4", "gpio5", +- "gpio6", "gpio7", "gpio8", "gpio9", +- "gpio10", "gpio11", "gpio12", "gpio13", +- "gpio14", "gpio15", "gpio16", "gpio17", +- "gpio18", "gpio19", "gpio20", "gpio21"; +- bias-disable; +- }; +- rp1_dpi_18bit_cpadhi_gpio2: rp1_dpi_18bit_cpadhi_gpio2 { /* Mode 6 */ +- function = "dpi"; +- pins = "gpio2", "gpio3", "gpio4", "gpio5", +- "gpio6", "gpio7", "gpio8", "gpio9", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", +- "gpio20", "gpio21", "gpio22", "gpio23", +- "gpio24", "gpio25"; +- bias-disable; +- }; +- rp1_dpi_24bit_gpio2: rp1_dpi_24bit_gpio2 { /* Mode 7 */ +- function = "dpi"; +- pins = "gpio2", "gpio3", "gpio4", "gpio5", +- "gpio6", "gpio7", "gpio8", "gpio9", +- "gpio10", "gpio11", "gpio12", "gpio13", +- "gpio14", "gpio15", "gpio16", "gpio17", +- "gpio18", "gpio19", "gpio20", "gpio21", +- "gpio22", "gpio23", "gpio24", "gpio25", +- "gpio26", "gpio27"; +- bias-disable; +- }; +- rp1_dpi_hvsync: rp1_dpi_hvsync { /* Sync only, for use with int VDAC */ +- function = "dpi"; +- pins = "gpio2", "gpio3"; +- bias-disable; +- }; +- +- // More DPI mappings, including PIXCLK,DE on GPIOs 0,1 +- rp1_dpi_16bit_gpio0: rp1_dpi_16bit_gpio0 { /* Mode 2, not fully supported by RP1 */ +- function = "dpi"; +- pins = "gpio0", "gpio1", "gpio2", "gpio3", +- "gpio4", "gpio5", "gpio6", "gpio7", +- "gpio8", "gpio9", "gpio10", "gpio11", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", "gpio18", "gpio19"; +- bias-disable; +- }; +- rp1_dpi_16bit_cpadhi_gpio0: rp1_dpi_16bit_cpadhi_gpio0 { /* Mode 3 */ +- function = "dpi"; +- pins = "gpio0", "gpio1", "gpio2", "gpio3", +- "gpio4", "gpio5", "gpio6", "gpio7", +- "gpio8", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", +- "gpio20", "gpio21", "gpio22", "gpio23", +- "gpio24"; +- bias-disable; +- }; +- rp1_dpi_16bit_pad666_gpio0: rp1_dpi_16bit_pad666_gpio0 { /* Mode 4 */ +- function = "dpi"; +- pins = "gpio0", "gpio1", "gpio2", "gpio3", +- "gpio5", "gpio6", "gpio7", "gpio8", +- "gpio9", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", +- "gpio21", "gpio22", "gpio23", "gpio24", +- "gpio25"; +- bias-disable; +- }; +- rp1_dpi_18bit_gpio0: rp1_dpi_18bit_gpio0 { /* Mode 5, not fully supported by RP1 */ +- function = "dpi"; +- pins = "gpio0", "gpio1", "gpio2", "gpio3", +- "gpio4", "gpio5", "gpio6", "gpio7", +- "gpio8", "gpio9", "gpio10", "gpio11", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", "gpio18", "gpio19", +- "gpio20", "gpio21"; +- bias-disable; +- }; +- rp1_dpi_18bit_cpadhi_gpio0: rp1_dpi_18bit_cpadhi_gpio0 { /* Mode 6 */ +- function = "dpi"; +- pins = "gpio0", "gpio1", "gpio2", "gpio3", +- "gpio4", "gpio5", "gpio6", "gpio7", +- "gpio8", "gpio9", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", +- "gpio20", "gpio21", "gpio22", "gpio23", +- "gpio24", "gpio25"; +- bias-disable; +- }; +- rp1_dpi_24bit_gpio0: rp1_dpi_24bit_gpio0 { /* Mode 7 -- All GPIOs used! */ +- function = "dpi"; +- pins = "gpio0", "gpio1", "gpio2", "gpio3", +- "gpio4", "gpio5", "gpio6", "gpio7", +- "gpio8", "gpio9", "gpio10", "gpio11", +- "gpio12", "gpio13", "gpio14", "gpio15", +- "gpio16", "gpio17", "gpio18", "gpio19", +- "gpio20", "gpio21", "gpio22", "gpio23", +- "gpio24", "gpio25", "gpio26", "gpio27"; +- bias-disable; +- }; +- +- rp1_gpclksrc0_gpio4: rp1_gpclksrc0_gpio4 { +- function = "gpclk0"; +- pins = "gpio4"; +- bias-disable; +- }; +- +- rp1_gpclksrc0_gpio20: rp1_gpclksrc0_gpio20 { +- function = "gpclk0"; +- pins = "gpio20"; +- bias-disable; +- }; +- +- rp1_gpclksrc1_gpio5: rp1_gpclksrc1_gpio5 { +- function = "gpclk1"; +- pins = "gpio5"; +- bias-disable; +- }; +- +- rp1_gpclksrc1_gpio18: rp1_gpclksrc1_gpio18 { +- function = "gpclk1"; +- pins = "gpio18"; +- bias-disable; +- }; +- +- rp1_gpclksrc1_gpio21: rp1_gpclksrc1_gpio21 { +- function = "gpclk1"; +- pins = "gpio21"; +- bias-disable; +- }; +- +- rp1_pwm1_gpio45: rp1_pwm1_gpio45 { +- function = "pwm1"; +- pins = "gpio45"; +- bias-pull-down; +- }; +- +- rp1_spi0_gpio9: rp1_spi0_gpio9 { +- function = "spi0"; +- pins = "gpio9", "gpio10", "gpio11"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- +- rp1_spi0_cs_gpio7: rp1_spi0_cs_gpio7 { +- function = "spi0"; +- pins = "gpio7", "gpio8"; +- bias-pull-up; +- }; +- +- rp1_spi1_gpio19: rp1_spi1_gpio19 { +- function = "spi1"; +- pins = "gpio19", "gpio20", "gpio21"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- +- rp1_spi2_gpio1: rp1_spi2_gpio1 { +- function = "spi2"; +- pins = "gpio1", "gpio2", "gpio3"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- +- rp1_spi3_gpio5: rp1_spi3_gpio5 { +- function = "spi3"; +- pins = "gpio5", "gpio6", "gpio7"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- +- rp1_spi4_gpio9: rp1_spi4_gpio9 { +- function = "spi4"; +- pins = "gpio9", "gpio10", "gpio11"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- +- rp1_spi5_gpio13: rp1_spi5_gpio13 { +- function = "spi5"; +- pins = "gpio13", "gpio14", "gpio15"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- +- rp1_spi8_gpio49: rp1_spi8_gpio49 { +- function = "spi8"; +- pins = "gpio49", "gpio50", "gpio51"; +- bias-disable; +- drive-strength = <12>; +- slew-rate = <1>; +- }; +- +- rp1_spi8_cs_gpio52: rp1_spi8_cs_gpio52 { +- function = "spi0"; +- pins = "gpio52", "gpio53"; +- bias-pull-up; +- }; +- }; +- +- rp1_eth: ethernet@100000 { +- reg = <0xc0 0x40100000 0x0 0x4000>; +- compatible = "cdns,macb"; +- #address-cells = <1>; +- #size-cells = <0>; +- interrupts = ; +- clocks = <&macb_pclk &macb_hclk &rp1_clocks RP1_CLK_ETH_TSU>; +- clock-names = "pclk", "hclk", "tsu_clk"; +- phy-mode = "rgmii-id"; +- cdns,aw2w-max-pipe = /bits/ 8 <8>; +- cdns,ar2r-max-pipe = /bits/ 8 <8>; +- cdns,use-aw2b-fill; +- local-mac-address = [00 00 00 00 00 00]; +- status = "disabled"; +- }; +- +- rp1_csi0: csi@110000 { +- compatible = "raspberrypi,rp1-cfe"; +- reg = <0xc0 0x40110000 0x0 0x100>, // CSI2 DMA address +- <0xc0 0x40114000 0x0 0x100>, // PHY/CSI Host address +- <0xc0 0x40120000 0x0 0x100>, // MIPI CFG address +- <0xc0 0x40124000 0x0 0x1000>; // PiSP FE address +- +- // interrupts must match rp1_pisp_fe setup +- interrupts = ; +- +- clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; +- assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; +- assigned-clock-rates = <25000000>; +- +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- rp1_csi1: csi@128000 { +- compatible = "raspberrypi,rp1-cfe"; +- reg = <0xc0 0x40128000 0x0 0x100>, // CSI2 DMA address +- <0xc0 0x4012c000 0x0 0x100>, // PHY/CSI Host address +- <0xc0 0x40138000 0x0 0x100>, // MIPI CFG address +- <0xc0 0x4013c000 0x0 0x1000>; // PiSP FE address +- +- // interrupts must match rp1_pisp_fe setup +- interrupts = ; +- +- clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; +- assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; +- assigned-clock-rates = <25000000>; +- +- #address-cells = <1>; +- #size-cells = <0>; +- status = "disabled"; +- }; +- +- rp1_mmc0: mmc@180000 { +- reg = <0xc0 0x40180000 0x0 0x100>; +- compatible = "raspberrypi,rp1-dwcmshc"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core +- &rp1_clocks RP1_CLK_SDIO_TIMER +- &rp1_sdio_clk0>; +- clock-names = "bus", "core", "timeout", "sdio"; +- /* Bank 0 VDDIO is fixed */ +- no-1-8-v; +- bus-width = <4>; +- vmmc-supply = <&rp1_vdd_3v3>; +- broken-cd; +- status = "disabled"; +- }; +- +- rp1_mmc1: mmc@184000 { +- reg = <0xc0 0x40184000 0x0 0x100>; +- compatible = "raspberrypi,rp1-dwcmshc"; +- interrupts = ; +- clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core +- &rp1_clocks RP1_CLK_SDIO_TIMER +- &rp1_sdio_clk1>; +- clock-names = "bus", "core", "timeout", "sdio"; +- bus-width = <4>; +- vmmc-supply = <&rp1_vdd_3v3>; +- /* Nerf SDR speeds */ +- sdhci-caps-mask = <0x3 0x0>; +- broken-cd; +- status = "disabled"; +- }; +- +- rp1_dma: dma@188000 { +- reg = <0xc0 0x40188000 0x0 0x1000>; +- compatible = "snps,axi-dma-1.01a"; +- interrupts = ; +- clocks = <&sdhci_core &rp1_clocks RP1_CLK_SYS>; +- clock-names = "core-clk", "cfgr-clk"; +- +- #dma-cells = <1>; +- dma-channels = <8>; +- snps,dma-masters = <1>; +- snps,dma-targets = <64>; +- snps,data-width = <4>; // (8 << 4) == 128 bits +- snps,block-size = <0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000>; +- snps,priority = <0 1 2 3 4 5 6 7>; +- snps,axi-max-burst-len = <8>; +- status = "disabled"; +- }; +- +- rp1_usb0: usb@200000 { +- reg = <0xc0 0x40200000 0x0 0x100000>; +- compatible = "snps,dwc3"; +- dr_mode = "host"; +- usb3-lpm-capable; +- snps,axi-pipe-limit = /bits/ 8 <8>; +- snps,dis_rxdet_inp3_quirk; +- snps,parkmode-disable-ss-quirk; +- snps,parkmode-disable-hs-quirk; +- snps,parkmode-disable-fsls-quirk; +- snps,tx-max-burst = /bits/ 8 <8>; +- snps,tx-thr-num-pkt = /bits/ 8 <2>; +- interrupts = ; +- status = "disabled"; +- }; +- +- rp1_usb1: usb@300000 { +- reg = <0xc0 0x40300000 0x0 0x100000>; +- compatible = "snps,dwc3"; +- dr_mode = "host"; +- usb3-lpm-capable; +- snps,axi-pipe-limit = /bits/ 8 <8>; +- snps,dis_rxdet_inp3_quirk; +- snps,parkmode-disable-ss-quirk; +- snps,parkmode-disable-hs-quirk; +- snps,parkmode-disable-fsls-quirk; +- snps,tx-max-burst = /bits/ 8 <8>; +- snps,tx-thr-num-pkt = /bits/ 8 <2>; +- interrupts = ; +- status = "disabled"; +- }; +- +- rp1_dsi0: dsi@110000 { +- compatible = "raspberrypi,rp1dsi"; +- status = "disabled"; +- reg = <0xc0 0x40118000 0x0 0x1000>, // MIPI0 DSI DMA (ArgonDPI) +- <0xc0 0x4011c000 0x0 0x1000>, // MIPI0 DSI Host (SNPS) +- <0xc0 0x40120000 0x0 0x1000>; // MIPI0 CFG +- +- interrupts = ; +- +- clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, +- <&rp1_clocks RP1_CLK_MIPI0_DPI>, +- <&rp1_clocks RP1_CLK_MIPI0_DSI_BYTECLOCK>, +- <&clk_xosc>, // hardwired to DSI "refclk" +- <&rp1_clocks RP1_PLL_SYS>; // alternate parent for divide +- clock-names = "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys"; +- +- assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; +- assigned-clock-rates = <25000000>; +- }; +- +- rp1_dsi1: dsi@128000 { +- compatible = "raspberrypi,rp1dsi"; +- status = "disabled"; +- reg = <0xc0 0x40130000 0x0 0x1000>, // MIPI1 DSI DMA (ArgonDPI) +- <0xc0 0x40134000 0x0 0x1000>, // MIPI1 DSI Host (SNPS) +- <0xc0 0x40138000 0x0 0x1000>; // MIPI1 CFG +- +- interrupts = ; +- +- clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, +- <&rp1_clocks RP1_CLK_MIPI1_DPI>, +- <&rp1_clocks RP1_CLK_MIPI1_DSI_BYTECLOCK>, +- <&clk_xosc>, // hardwired to DSI "refclk" +- <&rp1_clocks RP1_PLL_SYS>; // alternate parent for divide +- clock-names = "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys"; +- +- assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; +- assigned-clock-rates = <25000000>; +- }; +- +- /* VEC and DPI both need to control PLL_VIDEO and cannot work together; */ +- /* config.txt should enable one or other using dtparam=vec or an overlay. */ +- rp1_vec: vec@144000 { +- compatible = "raspberrypi,rp1vec"; +- status = "disabled"; +- reg = <0xc0 0x40144000 0x0 0x1000>, // VIDEO_OUT_VEC +- <0xc0 0x40140000 0x0 0x1000>; // VIDEO_OUT_CFG +- +- interrupts = ; +- +- clocks = <&rp1_clocks RP1_CLK_VEC>; +- +- assigned-clocks = <&rp1_clocks RP1_PLL_VIDEO_CORE>, +- <&rp1_clocks RP1_PLL_VIDEO_SEC>, +- <&rp1_clocks RP1_CLK_VEC>; +- assigned-clock-rates = <1188000000>, +- <108000000>, +- <108000000>; +- assigned-clock-parents = <0>, +- <&rp1_clocks RP1_PLL_VIDEO_CORE>, +- <&rp1_clocks RP1_PLL_VIDEO_SEC>; +- }; +- +- rp1_dpi: dpi@148000 { +- compatible = "raspberrypi,rp1dpi"; +- status = "disabled"; +- reg = <0xc0 0x40148000 0x0 0x1000>, // VIDEO_OUT DPI +- <0xc0 0x40140000 0x0 0x1000>; // VIDEO_OUT_CFG +- +- interrupts = ; +- +- clocks = <&rp1_clocks RP1_CLK_DPI>, // DPI pixel clock +- <&rp1_clocks RP1_PLL_VIDEO>, // PLL primary divider, and +- <&rp1_clocks RP1_PLL_VIDEO_CORE>; // VCO, which we also control +- clock-names = "dpiclk", "plldiv", "pllcore"; +- +- assigned-clocks = <&rp1_clocks RP1_CLK_DPI>; +- assigned-clock-parents = <&rp1_clocks RP1_PLL_VIDEO>; +- }; +- }; +-}; +- +-&clocks { +- clk_xosc: clk_xosc { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "xosc"; +- clock-frequency = <50000000>; +- }; +- macb_pclk: macb_pclk { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "pclk"; +- clock-frequency = <200000000>; +- }; +- macb_hclk: macb_hclk { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "hclk"; +- clock-frequency = <200000000>; +- }; +- sdio_src: sdio_src { +- // 400 MHz on FPGA. PLL sys VCO on asic +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "src"; +- clock-frequency = <1000000000>; +- }; +- sdhci_core: sdhci_core { +- compatible = "fixed-clock"; +- #clock-cells = <0>; +- clock-output-names = "core"; +- clock-frequency = <50000000>; +- }; +- /* GPIO derived clock sources. Each GPIO with a GPCLK function +- * can drive its output from the respective GPCLK +- * generator, and provide a clock source to other internal +- * dividers. Add dummy sources here so that they can be overridden +- * with overlays. +- */ +- clksrc_gp0: clksrc_gp0 { +- status = "disabled"; +- compatible = "fixed-factor-clock"; +- #clock-cells = <0>; +- clock-div = <1>; +- clock-mult = <1>; +- clocks = <&rp1_clocks RP1_CLK_GP0>; +- clock-output-names = "clksrc_gp0"; +- }; +- clksrc_gp1: clksrc_gp1 { +- status = "disabled"; +- compatible = "fixed-factor-clock"; +- #clock-cells = <0>; +- clock-div = <1>; +- clock-mult = <1>; +- clocks = <&rp1_clocks RP1_CLK_GP1>; +- clock-output-names = "clksrc_gp1"; +- }; +- clksrc_gp2: clksrc_gp2 { +- status = "disabled"; +- compatible = "fixed-factor-clock"; +- clock-div = <1>; +- clock-mult = <1>; +- #clock-cells = <0>; +- clocks = <&rp1_clocks RP1_CLK_GP2>; +- clock-output-names = "clksrc_gp2"; +- }; +- clksrc_gp3: clksrc_gp3 { +- status = "disabled"; +- compatible = "fixed-factor-clock"; +- clock-div = <1>; +- clock-mult = <1>; +- #clock-cells = <0>; +- clocks = <&rp1_clocks RP1_CLK_GP3>; +- clock-output-names = "clksrc_gp3"; +- }; +- clksrc_gp4: clksrc_gp4 { +- status = "disabled"; +- compatible = "fixed-factor-clock"; +- #clock-cells = <0>; +- clock-div = <1>; +- clock-mult = <1>; +- clocks = <&rp1_clocks RP1_CLK_GP4>; +- clock-output-names = "clksrc_gp4"; +- }; +- clksrc_gp5: clksrc_gp5 { +- status = "disabled"; +- compatible = "fixed-factor-clock"; +- #clock-cells = <0>; +- clock-div = <1>; +- clock-mult = <1>; +- clocks = <&rp1_clocks RP1_CLK_GP5>; +- clock-output-names = "clksrc_gp5"; +- }; +-}; +- +-/ { +- rp1_vdd_3v3: rp1_vdd_3v3 { +- compatible = "regulator-fixed"; +- regulator-name = "vdd-3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-always-on; +- }; +-}; +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi +@@ -0,0 +1,351 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++ ++&soc { ++ firmware: firmware { ++ compatible = "raspberrypi,bcm2835-firmware", "simple-mfd"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ mboxes = <&mailbox>; ++ dma-ranges; ++ ++ firmware_clocks: clocks { ++ compatible = "raspberrypi,firmware-clocks"; ++ #clock-cells = <1>; ++ }; ++ ++ reset: reset { ++ compatible = "raspberrypi,firmware-reset"; ++ #reset-cells = <1>; ++ }; ++ ++ vcio: vcio { ++ compatible = "raspberrypi,vcio"; ++ }; ++ }; ++ ++ power: power { ++ compatible = "raspberrypi,bcm2835-power"; ++ firmware = <&firmware>; ++ #power-domain-cells = <1>; ++ }; ++ ++ fb: fb { ++ compatible = "brcm,bcm2708-fb"; ++ firmware = <&firmware>; ++ status = "okay"; ++ }; ++ ++ rpi_rtc: rpi_rtc { ++ compatible = "raspberrypi,rpi-rtc"; ++ firmware = <&firmware>; ++ status = "okay"; ++ trickle-charge-microvolt = <0>; ++ }; ++ ++ nvmem { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ nvmem_otp: nvmem_otp { ++ compatible = "raspberrypi,rpi-otp"; ++ firmware = <&firmware>; ++ reg = <0 192>; ++ status = "okay"; ++ }; ++ ++ nvmem_cust: nvmem_cust { ++ compatible = "raspberrypi,rpi-otp"; ++ firmware = <&firmware>; ++ reg = <1 8>; ++ status = "okay"; ++ }; ++ ++ nvmem_mac: nvmem_mac { ++ compatible = "raspberrypi,rpi-otp"; ++ firmware = <&firmware>; ++ reg = <2 6>; ++ status = "okay"; ++ }; ++ ++ nvmem_priv: nvmem_priv { ++ compatible = "raspberrypi,rpi-otp"; ++ firmware = <&firmware>; ++ reg = <3 16>; ++ status = "okay"; ++ }; ++ }; ++ ++ /* Define these notional regulators for use by overlays, etc. */ ++ vdd_3v3_reg: fixedregulator_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-max-microvolt = <3300000>; ++ regulator-min-microvolt = <3300000>; ++ regulator-name = "3v3"; ++ }; ++ ++ vdd_5v0_reg: fixedregulator_5v0 { ++ compatible = "regulator-fixed"; ++ regulator-always-on; ++ regulator-max-microvolt = <5000000>; ++ regulator-min-microvolt = <5000000>; ++ regulator-name = "5v0"; ++ }; ++}; ++ ++/ { ++ __overrides__ { ++ arm_freq; ++ axiperf = <&axiperf>,"status"; ++ ++ nvmem_cust_rw = <&nvmem_cust>,"rw?"; ++ nvmem_priv_rw = <&nvmem_priv>,"rw?"; ++ nvmem_mac_rw = <&nvmem_mac>,"rw?"; ++ strict_gpiod = <&chosen>, "bootargs=pinctrl_rp1.persist_gpio_outputs=n"; ++ ++ cam0_reg = <&cam0_reg>,"status"; ++ cam0_reg_gpio = <&cam0_reg>,"gpio:4", ++ <&cam0_reg>,"gpio:0=", <&gpio>; ++ cam1_reg = <&cam1_reg>,"status"; ++ cam1_reg_gpio = <&cam1_reg>,"gpio:4", ++ <&cam1_reg>,"gpio:0=", <&gpio>; ++ ++ }; ++}; ++ ++pciex1: &pcie1 { }; ++pciex4: &pcie2 { }; ++ ++&dma32 { ++ /* The VPU firmware uses DMA channel 11 for VCHIQ */ ++ brcm,dma-channel-mask = <0x03f>; ++}; ++ ++&dma40 { ++ /* The VPU firmware DMA channel 11 for VCHIQ */ ++ brcm,dma-channel-mask = <0x07c0>; ++}; ++ ++&hdmi0 { ++ dmas = <&dma40 (10|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; ++}; ++ ++&hdmi1 { ++ dmas = <&dma40 (17|(1<<30)|(1<<24)|(10<<16)|(15<<20))>; ++}; ++ ++&spi10 { ++ dmas = <&dma40 6>, <&dma40 7>; ++ dma-names = "tx", "rx"; ++}; ++ ++&usb { ++ power-domains = <&power RPI_POWER_DOMAIN_USB>; ++}; ++ ++&rmem { ++ /* ++ * RPi5's co-processor will copy the board's bootloader configuration ++ * into memory for the OS to consume. It'll also update this node with ++ * its placement information. ++ */ ++ blconfig: nvram@0 { ++ compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x0 0x0 0x0>; ++ no-map; ++ status = "disabled"; ++ }; ++ /* ++ * RPi5 will copy the binary public key blob (if present) from the bootloader ++ * into memory for use by the OS. ++ */ ++ blpubkey: nvram@1 { ++ compatible = "raspberrypi,bootloader-public-key", "nvmem-rmem"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x0 0x0 0x0>; ++ no-map; ++ status = "disabled"; ++ }; ++}; ++ ++&rp1_adc { ++ status = "okay"; ++}; ++ ++/* Add some gpiomem nodes to make the devices accessible to userspace. ++ * /dev/gpiomem should expose the registers for the interface with DT alias ++ * gpio. ++ */ ++ ++&rp1 { ++ gpiomem@d0000 { ++ /* Export IO_BANKs, RIO_BANKs and PADS_BANKs to userspace */ ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0xc0 0x400d0000 0x0 0x30000>; ++ chardev-name = "gpiomem0"; ++ }; ++}; ++ ++&soc { ++ gpiomem@7d508500 { ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0x7d508500 0x40>; ++ chardev-name = "gpiomem1"; ++ }; ++ ++ gpiomem@7d517c00 { ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0x7d517c00 0x40>; ++ chardev-name = "gpiomem2"; ++ }; ++ ++ gpiomem@7d504100 { ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0x7d504100 0x20>; ++ chardev-name = "gpiomem3"; ++ }; ++ ++ gpiomem@7d510700 { ++ compatible = "raspberrypi,gpiomem"; ++ reg = <0x7d510700 0x20>; ++ chardev-name = "gpiomem4"; ++ }; ++ ++ sound: sound { ++ status = "disabled"; ++ }; ++}; ++ ++i2c0: &rp1_i2c0 { }; ++i2c1: &rp1_i2c1 { }; ++i2c2: &rp1_i2c2 { }; ++i2c3: &rp1_i2c3 { }; ++i2c4: &rp1_i2c4 { }; ++i2c5: &rp1_i2c5 { }; ++i2c6: &rp1_i2c6 { }; ++i2s: &rp1_i2s0 { }; ++i2s_clk_producer: &rp1_i2s0 { }; ++i2s_clk_consumer: &rp1_i2s1 { }; ++pwm0: &rp1_pwm0 { }; ++pwm1: &rp1_pwm1 { }; ++pwm: &pwm0 { }; ++spi0: &rp1_spi0 { }; ++spi1: &rp1_spi1 { }; ++spi2: &rp1_spi2 { }; ++spi3: &rp1_spi3 { }; ++spi4: &rp1_spi4 { }; ++spi5: &rp1_spi5 { }; ++ ++uart0_pins: &rp1_uart0_14_15 {}; ++uart0_ctsrts_pins: &rp1_uart0_ctsrts_16_17 {}; ++uart0: &rp1_uart0 { ++ pinctrl-0 = <&uart0_pins>; ++}; ++ ++uart1_pins: &rp1_uart1_0_1 {}; ++uart1_ctsrts_pins: &rp1_uart1_ctsrts_2_3 {}; ++uart1: &rp1_uart1 { }; ++ ++uart2_pins: &rp1_uart2_4_5 {}; ++uart2_ctsrts_pins: &rp1_uart2_ctsrts_6_7 {}; ++uart2: &rp1_uart2 { }; ++ ++uart3_pins: &rp1_uart3_8_9 {}; ++uart3_ctsrts_pins: &rp1_uart3_ctsrts_10_11 {}; ++uart3: &rp1_uart3 { }; ++ ++uart4_pins: &rp1_uart4_12_13 {}; ++uart4_ctsrts_pins: &rp1_uart4_ctsrts_14_15 {}; ++uart4: &rp1_uart4 { }; ++ ++i2c0_pins: &rp1_i2c0_0_1 {}; ++i2c_vc: &i2c0 { // This is pins 27,28 on the header (not MIPI) ++ pinctrl-0 = <&i2c0_pins>; ++ pinctrl-names = "default"; ++ clock-frequency = <100000>; ++}; ++ ++i2c1_pins: &rp1_i2c1_2_3 {}; ++i2c_arm: &i2c1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ clock-frequency = <100000>; ++}; ++ ++i2c2_pins: &rp1_i2c2_4_5 {}; ++&i2c2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++}; ++ ++i2c3_pins: &rp1_i2c3_6_7 {}; ++&i2c3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c3_pins>; ++}; ++ ++&i2s_clk_producer { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2s0_18_21>; ++}; ++ ++&i2s_clk_consumer { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rp1_i2s1_18_21>; ++}; ++ ++spi0_pins: &rp1_spi0_gpio9 {}; ++spi0_cs_pins: &rp1_spi0_cs_gpio7 {}; ++ ++&spi0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins &spi0_cs_pins>; ++ cs-gpios = <&gpio 8 1>, <&gpio 7 1>; ++ ++ spidev0: spidev@0 { ++ compatible = "spidev"; ++ reg = <0>; /* CE0 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ }; ++ ++ spidev1: spidev@1 { ++ compatible = "spidev"; ++ reg = <1>; /* CE1 */ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ spi-max-frequency = <125000000>; ++ }; ++}; ++ ++spi2_pins: &rp1_spi2_gpio1 {}; ++&spi2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2_pins>; ++}; ++ ++spi3_pins: &rp1_spi3_gpio5 {}; ++&spi3 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi3_pins>; ++}; ++ ++spi4_pins: &rp1_spi4_gpio9 {}; ++&spi4 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi4_pins>; ++}; ++ ++spi5_pins: &rp1_spi5_gpio13 {}; ++&spi5 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi5_pins>; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi +@@ -0,0 +1,1302 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include ++#include ++ ++/ { ++ compatible = "brcm,bcm2712", "brcm,bcm2711"; ++ model = "BCM2712"; ++ ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ++ interrupt-parent = <&gicv2>; ++ ++ rmem: reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ ranges; ++ ++ atf@0 { ++ reg = <0x0 0x0 0x80000>; ++ no-map; ++ }; ++ ++ cma: linux,cma { ++ compatible = "shared-dma-pool"; ++ size = <0x4000000>; /* 64MB */ ++ reusable; ++ linux,cma-default; ++ ++ /* ++ * arm64 reserves the CMA by default somewhere in ++ * ZONE_DMA32, that's not good enough for the BCM2711 ++ * as some devices can only address the lower 1G of ++ * memory (ZONE_DMA). ++ */ ++ alloc-ranges = <0x0 0x00000000 0x40000000>; ++ }; ++ }; ++ ++ thermal-zones { ++ cpu_thermal: cpu-thermal { ++ polling-delay-passive = <2000>; ++ polling-delay = <1000>; ++ coefficients = <(-550) 450000>; ++ thermal-sensors = <&thermal>; ++ ++ thermal_trips: trips { ++ cpu_crit: cpu-crit { ++ temperature = <110000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling_maps: cooling-maps { ++ }; ++ }; ++ }; ++ ++ clk_27MHz: clk-27M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <27000000>; ++ clock-output-names = "27MHz-clock"; ++ }; ++ ++ clk_108MHz: clk-108M { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <108000000>; ++ clock-output-names = "108MHz-clock"; ++ }; ++ ++ hvs: hvs@107c580000 { ++ compatible = "brcm,bcm2712-hvs"; ++ reg = <0x10 0x7c580000 0x1a000>; ++ interrupt-parent = <&disp_intr>; ++ interrupts = <2>, <9>, <16>; ++ interrupt-names = "ch0-eof", "ch1-eof", "ch2-eof"; ++ //iommus = <&iommu4>; ++ status = "disabled"; ++ }; ++ ++ soc: soc { ++ compatible = "simple-bus"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ ranges = <0x7c000000 0x10 0x7c000000 0x04000000>; ++ /* Emulate a contiguous 30-bit address range for DMA */ ++ dma-ranges = <0xc0000000 0x00 0x00000000 0x40000000>, ++ <0x7c000000 0x10 0x7c000000 0x04000000>; ++ ++ system_timer: timer@7c003000 { ++ compatible = "brcm,bcm2835-system-timer"; ++ reg = <0x7c003000 0x1000>; ++ interrupts = , ++ , ++ , ++ ; ++ clock-frequency = <1000000>; ++ }; ++ ++ firmwarekms: firmwarekms@7d503000 { ++ compatible = "raspberrypi,rpi-firmware-kms-2712"; ++ /* SUN_L2 interrupt reg */ ++ reg = <0x7d503000 0x18>; ++ interrupt-parent = <&cpu_l2_irq>; ++ interrupts = <19>; ++ brcm,firmware = <&firmware>; ++ status = "disabled"; ++ }; ++ ++ axiperf: axiperf { ++ compatible = "brcm,bcm2712-axiperf"; ++ reg = <0x7c012800 0x100>, ++ <0x7e000000 0x100>; ++ firmware = <&firmware>; ++ status = "disabled"; ++ }; ++ ++ mailbox: mailbox@7c013880 { ++ compatible = "brcm,bcm2835-mbox"; ++ reg = <0x7c013880 0x40>; ++ interrupts = ; ++ #mbox-cells = <0>; ++ }; ++ ++ pixelvalve0: pixelvalve@7c410000 { ++ compatible = "brcm,bcm2712-pixelvalve0"; ++ reg = <0x7c410000 0x100>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ pixelvalve1: pixelvalve@7c411000 { ++ compatible = "brcm,bcm2712-pixelvalve1"; ++ reg = <0x7c411000 0x100>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ mop: mop@7c500000 { ++ compatible = "brcm,bcm2712-mop"; ++ reg = <0x7c500000 0x28>; ++ interrupt-parent = <&disp_intr>; ++ interrupts = <1>; ++ status = "disabled"; ++ }; ++ ++ moplet: moplet@7c501000 { ++ compatible = "brcm,bcm2712-moplet"; ++ reg = <0x7c501000 0x20>; ++ interrupt-parent = <&disp_intr>; ++ interrupts = <0>; ++ status = "disabled"; ++ }; ++ ++ disp_intr: interrupt-controller@7c502000 { ++ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; ++ reg = <0x7c502000 0x30>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ dvp: clock@7c700000 { ++ compatible = "brcm,brcm2711-dvp"; ++ reg = <0x7c700000 0x10>; ++ clocks = <&clk_108MHz>; ++ #clock-cells = <1>; ++ #reset-cells = <1>; ++ }; ++ ++ /* ++ * This node is the provider for the enable-method for ++ * bringing up secondary cores. ++ */ ++ local_intc: local_intc@7cd00000 { ++ compatible = "brcm,bcm2836-l1-intc"; ++ reg = <0x7cd00000 0x100>; ++ }; ++ ++ uart0: serial@7d001000 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001000 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ uart2: serial@7d001400 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001400 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ uart5: serial@7d001a00 { ++ compatible = "arm,pl011", "arm,primecell"; ++ reg = <0x7d001a00 0x200>; ++ interrupts = ; ++ clocks = <&clk_uart>, ++ <&clk_vpu>; ++ clock-names = "uartclk", "apb_pclk"; ++ arm,primecell-periphid = <0x00241011>; ++ status = "disabled"; ++ }; ++ ++ sdhost: mmc@7d002000 { ++ compatible = "brcm,bcm2835-sdhost"; ++ reg = <0x7d002000 0x100>; ++ //interrupts = ; ++ clocks = <&clk_vpu>; ++ status = "disabled"; ++ }; ++ ++ i2s: i2s@7d003000 { ++ compatible = "brcm,bcm2835-i2s"; ++ reg = <0x7d003000 0x24>; ++ //clocks = <&cprman BCM2835_CLOCK_PCM>; ++ status = "disabled"; ++ }; ++ ++ spi0: spi@7d004000 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004000 0x200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ num-cs = <1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi3: spi@7d004600 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004600 0x0200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi4: spi@7d004800 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004800 0x0200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi5: spi@7d004a00 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004a00 0x0200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ spi6: spi@7d004c00 { ++ compatible = "brcm,bcm2835-spi"; ++ reg = <0x7d004c00 0x0200>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c@7d005000 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005000 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c@7d005600 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005600 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c4: i2c@7d005800 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005800 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c5: i2c@7d005a00 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005a00 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c6: i2c@7d005c00 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005c00 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2c8: i2c@7d005e00 { ++ compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; ++ reg = <0x7d005e00 0x20>; ++ interrupts = ; ++ clocks = <&clk_vpu>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ pwm0: pwm@7d00c000 { ++ compatible = "brcm,bcm2835-pwm"; ++ reg = <0x7d00c000 0x28>; ++ assigned-clock-rates = <50000000>; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pwm1: pwm@7d00c800 { ++ compatible = "brcm,bcm2835-pwm"; ++ reg = <0x7d00c800 0x28>; ++ assigned-clock-rates = <50000000>; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ ++ pm: watchdog@7d200000 { ++ compatible = "brcm,bcm2712-pm"; ++ reg = <0x7d200000 0x308>; ++ reg-names = "pm"; ++ #power-domain-cells = <1>; ++ #reset-cells = <1>; ++ //clocks = <&cprman BCM2835_CLOCK_V3D>, ++ // <&cprman BCM2835_CLOCK_PERI_IMAGE>, ++ // <&cprman BCM2835_CLOCK_H264>, ++ // <&cprman BCM2835_CLOCK_ISP>; ++ clock-names = "v3d", "peri_image", "h264", "isp"; ++ system-power-controller; ++ }; ++ ++ cprman: cprman@7d202000 { ++ compatible = "brcm,bcm2711-cprman"; ++ reg = <0x7d202000 0x2000>; ++ #clock-cells = <1>; ++ ++ /* CPRMAN derives almost everything from the ++ * platform's oscillator. However, the DSI ++ * pixel clocks come from the DSI analog PHY. ++ */ ++ clocks = <&clk_osc>; ++ status = "disabled"; ++ }; ++ ++ random: rng@7d208000 { ++ compatible = "brcm,bcm2711-rng200"; ++ reg = <0x7d208000 0x28>; ++ status = "okay"; ++ }; ++ ++ cpu_l2_irq: intc@7d503000 { ++ compatible = "brcm,l2-intc"; ++ reg = <0x7d503000 0x18>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ pinctrl: pinctrl@7d504100 { ++ compatible = "brcm,bcm2712-pinctrl"; ++ reg = <0x7d504100 0x30>; ++ ++ uarta_24_pins: uarta_24_pins { ++ pin_rts { ++ function = "uart0"; ++ pins = "gpio24"; ++ bias-disable; ++ }; ++ pin_cts { ++ function = "uart0"; ++ pins = "gpio25"; ++ bias-pull-up; ++ }; ++ pin_txd { ++ function = "uart0"; ++ pins = "gpio26"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart0"; ++ pins = "gpio27"; ++ bias-pull-up; ++ }; ++ }; ++ ++ sdio2_30_pins: sdio2_30_pins { ++ pin_clk { ++ function = "sd2"; ++ pins = "gpio30"; ++ bias-disable; ++ }; ++ pin_cmd { ++ function = "sd2"; ++ pins = "gpio31"; ++ bias-pull-up; ++ }; ++ pins_dat { ++ function = "sd2"; ++ pins = "gpio32", "gpio33", "gpio34", "gpio35"; ++ bias-pull-up; ++ }; ++ }; ++ }; ++ ++ ddc0: i2c@7d508200 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d508200 0x58>; ++ interrupt-parent = <&bsc_irq>; ++ interrupts = <1>; ++ clock-frequency = <97500>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ ddc1: i2c@7d508280 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d508280 0x58>; ++ interrupt-parent = <&bsc_irq>; ++ interrupts = <2>; ++ clock-frequency = <97500>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ bscd: i2c@7d508300 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d508300 0x58>; ++ interrupt-parent = <&bsc_irq>; ++ interrupts = <0>; ++ clock-frequency = <200000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ bsc_irq: intc@7d508380 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d508380 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ main_irq: intc@7d508400 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d508400 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gio: gpio@7d508500 { ++ compatible = "brcm,brcmstb-gpio"; ++ reg = <0x7d508500 0x40>; ++ interrupt-parent = <&main_irq>; ++ interrupts = <0>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ brcm,gpio-bank-widths = <32 22>; ++ brcm,gpio-direct; ++ }; ++ ++ uarta: serial@7d50c000 { ++ compatible = "brcm,bcm7271-uart"; ++ reg = <0x7d50c000 0x20>; ++ reg-names = "uart"; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ interrupts = ; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ uartb: serial@7d50d000 { ++ compatible = "brcm,bcm7271-uart"; ++ reg = <0x7d50d000 0x20>; ++ reg-names = "uart"; ++ reg-shift = <2>; ++ reg-io-width = <4>; ++ interrupts = ; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ aon_intr: interrupt-controller@7d510600 { ++ compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; ++ reg = <0x7d510600 0x30>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ pinctrl_aon: pinctrl@7d510700 { ++ compatible = "brcm,bcm2712-aon-pinctrl"; ++ reg = <0x7d510700 0x20>; ++ ++ i2c3_m4_agpio0_pins: i2c3_m4_agpio0_pins { ++ function = "vc_i2c3"; ++ pins = "aon_gpio0", "aon_gpio1"; ++ bias-pull-up; ++ }; ++ ++ bsc_m1_agpio13_pins: bsc_m1_agpio13_pins { ++ function = "bsc_m1"; ++ pins = "aon_gpio13", "aon_gpio14"; ++ bias-pull-up; ++ }; ++ ++ bsc_pmu_sgpio4_pins: bsc_pmu_sgpio4_pins { ++ function = "avs_pmu_bsc"; ++ pins = "aon_sgpio4", "aon_sgpio5"; ++ }; ++ ++ bsc_m2_sgpio4_pins: bsc_m2_sgpio4_pins { ++ function = "bsc_m2"; ++ pins = "aon_sgpio4", "aon_sgpio5"; ++ }; ++ ++ pwm_aon_agpio1_pins: pwm_aon_agpio1_pins { ++ function = "aon_pwm"; ++ pins = "aon_gpio1", "aon_gpio2"; ++ }; ++ ++ pwm_aon_agpio4_pins: pwm_aon_agpio4_pins { ++ function = "vc_pwm0"; ++ pins = "aon_gpio4", "aon_gpio5"; ++ }; ++ ++ pwm_aon_agpio7_pins: pwm_aon_agpio7_pins { ++ function = "aon_pwm"; ++ pins = "aon_gpio7", "aon_gpio9"; ++ }; ++ }; ++ ++ intc@7d517000 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d517000 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ status = "disabled"; ++ }; ++ ++ bscc: i2c@7d517a00 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d517a00 0x58>; ++ interrupt-parent = <&bsc_aon_irq>; ++ interrupts = <0>; ++ clock-frequency = <200000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ pwm_aon: pwm@7d517a80 { ++ compatible = "brcm,bcm7038-pwm"; ++ reg = <0x7d517a80 0x28>; ++ #pwm-cells = <3>; ++ clocks = <&clk_27MHz>; ++ }; ++ ++ main_aon_irq: intc@7d517ac0 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d517ac0 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ bsc_aon_irq: intc@7d517b00 { ++ compatible = "brcm,bcm7271-l2-intc"; ++ reg = <0x7d517b00 0x10>; ++ interrupts = ; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ }; ++ ++ gio_aon: gpio@7d517c00 { ++ compatible = "brcm,brcmstb-gpio"; ++ reg = <0x7d517c00 0x40>; ++ interrupt-parent = <&main_aon_irq>; ++ interrupts = <0>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ brcm,gpio-bank-widths = <17 6>; ++ brcm,gpio-direct; ++ }; ++ ++ avs_monitor: avs-monitor@7d542000 { ++ compatible = "brcm,bcm2711-avs-monitor", ++ "syscon", "simple-mfd"; ++ reg = <0x7d542000 0xf00>; ++ status = "okay"; ++ ++ thermal: thermal { ++ compatible = "brcm,bcm2711-thermal"; ++ #thermal-sensor-cells = <0>; ++ }; ++ }; ++ ++ bsc_pmu: i2c@7d544000 { ++ compatible = "brcm,brcmstb-i2c"; ++ reg = <0x7d544000 0x58>; ++ interrupt-parent = <&bsc_aon_irq>; ++ interrupts = <1>; ++ clock-frequency = <200000>; ++ status = "disabled"; ++ }; ++ ++ hdmi0: hdmi@7ef00700 { ++ compatible = "brcm,bcm2712-hdmi0"; ++ reg = <0x7c701400 0x300>, ++ <0x7c701000 0x200>, ++ <0x7c701d00 0x300>, ++ <0x7c702000 0x80>, ++ <0x7c703800 0x200>, ++ <0x7c704000 0x800>, ++ <0x7c700100 0x80>, ++ <0x7d510800 0x100>, ++ <0x7c720000 0x100>; ++ reg-names = "hdmi", ++ "dvp", ++ "phy", ++ "rm", ++ "packet", ++ "metadata", ++ "csc", ++ "cec", ++ "hd"; ++ resets = <&dvp 1>; ++ interrupt-parent = <&aon_intr>; ++ interrupts = <1>, <2>, <3>, ++ <7>, <8>; ++ interrupt-names = "cec-tx", "cec-rx", "cec-low", ++ "hpd-connected", "hpd-removed"; ++ ddc = <&ddc0>; ++ dmas = <&dma32 10>; ++ dma-names = "audio-rx"; ++ status = "disabled"; ++ }; ++ ++ hdmi1: hdmi@7ef05700 { ++ compatible = "brcm,bcm2712-hdmi1"; ++ reg = <0x7c706400 0x300>, ++ <0x7c706000 0x200>, ++ <0x7c706d00 0x300>, ++ <0x7c707000 0x80>, ++ <0x7c708800 0x200>, ++ <0x7c709000 0x800>, ++ <0x7c700180 0x80>, ++ <0x7d511000 0x100>, ++ <0x7c720000 0x100>; ++ reg-names = "hdmi", ++ "dvp", ++ "phy", ++ "rm", ++ "packet", ++ "metadata", ++ "csc", ++ "cec", ++ "hd"; ++ ddc = <&ddc1>; ++ resets = <&dvp 2>; ++ interrupt-parent = <&aon_intr>; ++ interrupts = <11>, <12>, <13>, ++ <14>, <15>; ++ interrupt-names = "cec-tx", "cec-rx", "cec-low", ++ "hpd-connected", "hpd-removed"; ++ dmas = <&dma32 17>; ++ dma-names = "audio-rx"; ++ status = "disabled"; ++ }; ++ }; ++ ++ arm-pmu { ++ compatible = "arm,cortex-a76-pmu"; ++ interrupts = , ++ , ++ , ++ ; ++ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = , ++ , ++ , ++ ; ++ /* This only applies to the ARMv7 stub */ ++ arm,cpu-registers-not-fw-configured; ++ }; ++ ++ cpus: cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit ++ ++ /* Source for d/i cache-line-size, cache-sets, cache-size ++ * https://developer.arm.com/documentation/100798/0401 ++ * /L1-memory-system/About-the-L1-memory-system?lang=en ++ */ ++ cpu0: cpu@0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x000>; ++ enable-method = "psci"; ++ d-cache-size = <0x10000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set ++ i-cache-size = <0x10000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set ++ next-level-cache = <&l2_cache_l0>; ++ }; ++ ++ cpu1: cpu@1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x100>; ++ enable-method = "psci"; ++ d-cache-size = <0x10000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set ++ i-cache-size = <0x10000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set ++ next-level-cache = <&l2_cache_l1>; ++ }; ++ ++ cpu2: cpu@2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x200>; ++ enable-method = "psci"; ++ d-cache-size = <0x10000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set ++ i-cache-size = <0x10000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set ++ next-level-cache = <&l2_cache_l2>; ++ }; ++ ++ cpu3: cpu@3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a76"; ++ reg = <0x300>; ++ enable-method = "psci"; ++ d-cache-size = <0x10000>; ++ d-cache-line-size = <64>; ++ d-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set ++ i-cache-size = <0x10000>; ++ i-cache-line-size = <64>; ++ i-cache-sets = <256>; // 64KiB(size)/64(line-size)=1024ways/4-way set ++ next-level-cache = <&l2_cache_l3>; ++ }; ++ ++ /* Source for cache-line-size and cache-sets: ++ * https://developer.arm.com/documentation/100798/0401 ++ * /L2-memory-system/About-the-L2-memory-system?lang=en ++ * and for cache-size: ++ * https://www.raspberrypi.com/documentation/computers ++ * /processors.html#bcm2712 ++ */ ++ l2_cache_l0: l2-cache-l0 { ++ compatible = "cache"; ++ cache-size = <0x80000>; ++ cache-line-size = <128>; ++ cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set ++ cache-level = <2>; ++ cache-unified; ++ next-level-cache = <&l3_cache>; ++ }; ++ ++ l2_cache_l1: l2-cache-l1 { ++ compatible = "cache"; ++ cache-size = <0x80000>; ++ cache-line-size = <128>; ++ cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set ++ cache-level = <2>; ++ cache-unified; ++ next-level-cache = <&l3_cache>; ++ }; ++ ++ l2_cache_l2: l2-cache-l2 { ++ compatible = "cache"; ++ cache-size = <0x80000>; ++ cache-line-size = <128>; ++ cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set ++ cache-level = <2>; ++ cache-unified; ++ next-level-cache = <&l3_cache>; ++ }; ++ ++ l2_cache_l3: l2-cache-l3 { ++ compatible = "cache"; ++ cache-size = <0x80000>; ++ cache-line-size = <128>; ++ cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set ++ cache-level = <2>; ++ cache-unified; ++ next-level-cache = <&l3_cache>; ++ }; ++ ++ /* Source for cache-line-size and cache-sets: ++ * https://developer.arm.com/documentation/100453/0401/L3-cache?lang=en ++ * Source for cache-size: ++ * https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712 ++ */ ++ l3_cache: l3-cache { ++ compatible = "cache"; ++ cache-size = <0x200000>; ++ cache-line-size = <64>; ++ cache-sets = <2048>; // 2MiB(size)/64(line-size)=32768ways/16-way set ++ cache-level = <3>; ++ }; ++ }; ++ ++ psci { ++ method = "smc"; ++ compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; ++ cpu_on = <0xc4000003>; ++ cpu_suspend = <0xc4000001>; ++ cpu_off = <0x84000002>; ++ }; ++ ++ axi: axi { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ ranges = <0x00 0x00000000 0x00 0x00000000 0x10 0x00000000>, ++ <0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>, ++ <0x14 0x00000000 0x14 0x00000000 0x04 0x00000000>, ++ <0x18 0x00000000 0x18 0x00000000 0x04 0x00000000>, ++ <0x1c 0x00000000 0x1c 0x00000000 0x04 0x00000000>; ++ ++ dma-ranges = <0x00 0x00000000 0x00 0x00000000 0x10 0x00000000>, ++ <0x10 0x00000000 0x10 0x00000000 0x01 0x00000000>, ++ <0x14 0x00000000 0x14 0x00000000 0x04 0x00000000>, ++ <0x18 0x00000000 0x18 0x00000000 0x04 0x00000000>, ++ <0x1c 0x00000000 0x1c 0x00000000 0x04 0x00000000>; ++ ++ vc4: gpu { ++ compatible = "brcm,bcm2712-vc6"; ++ }; ++ ++ iommu2: iommu@5100 { ++ /* IOMMU2 for PISP-BE, HEVC; and (unused) H264 accelerators */ ++ compatible = "brcm,bcm2712-iommu"; ++ reg = <0x10 0x5100 0x0 0x80>; ++ cache = <&iommuc>; ++ #iommu-cells = <0>; ++ }; ++ ++ iommu4: iommu@5200 { ++ /* IOMMU4 for HVS, MPL/TXP; and (unused) Unicam, PISP-FE, MiniBVN */ ++ compatible = "brcm,bcm2712-iommu"; ++ reg = <0x10 0x5200 0x0 0x80>; ++ cache = <&iommuc>; ++ #iommu-cells = <0>; ++ #interconnect-cells = <0>; ++ }; ++ ++ iommu5: iommu@5280 { ++ /* IOMMU5 for PCIe2 (RP1); and (unused) BSTM */ ++ compatible = "brcm,bcm2712-iommu"; ++ reg = <0x10 0x5280 0x0 0x80>; ++ cache = <&iommuc>; ++ #iommu-cells = <0>; ++ dma-iova-offset = <0x10 0x00000000>; // HACK for RP1 masters over PCIe ++ }; ++ ++ iommuc: iommuc@5b00 { ++ compatible = "brcm,bcm2712-iommuc"; ++ reg = <0x10 0x5b00 0x0 0x80>; ++ }; ++ ++ dma32: dma@10000 { ++ compatible = "brcm,bcm2712-dma"; ++ reg = <0x10 0x00010000 0 0x600>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = "dma0", ++ "dma1", ++ "dma2", ++ "dma3", ++ "dma4", ++ "dma5"; ++ #dma-cells = <1>; ++ brcm,dma-channel-mask = <0x0035>; ++ }; ++ ++ dma40: dma@10600 { ++ compatible = "brcm,bcm2712-dma"; ++ reg = <0x10 0x00010600 0 0x600>; ++ interrupts = ++ , /* dma4 6 */ ++ , /* dma4 7 */ ++ , /* dma4 8 */ ++ , /* dma4 9 */ ++ , /* dma4 10 */ ++ ; /* dma4 11 */ ++ interrupt-names = "dma6", ++ "dma7", ++ "dma8", ++ "dma9", ++ "dma10", ++ "dma11"; ++ #dma-cells = <1>; ++ brcm,dma-channel-mask = <0x0fc0>; ++ }; ++ ++ // Single-lane Gen3 PCIe ++ // Outbound window at 0x14_000000-0x17_ffffff ++ pcie0: pcie@100000 { ++ compatible = "brcm,bcm2712-pcie"; ++ reg = <0x10 0x00100000 0x0 0x9310>; ++ device_type = "pci"; ++ max-link-speed = <2>; ++ #address-cells = <3>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ /* ++ * Unused interrupts: ++ * 208: AER ++ * 215: NMI ++ * 216: PME ++ */ ++ interrupt-parent = <&gicv2>; ++ interrupts = , ++ ; ++ interrupt-names = "pcie", "msi"; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 209 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 2 &gicv2 GIC_SPI 210 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 3 &gicv2 GIC_SPI 211 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 4 &gicv2 GIC_SPI 212 ++ IRQ_TYPE_LEVEL_HIGH>; ++ resets = <&bcm_reset 5>, <&bcm_reset 42>, <&pcie_rescal>; ++ reset-names = "swinit", "bridge", "rescal"; ++ msi-controller; ++ msi-parent = <&pcie0>; ++ ++ ranges = <0x02000000 0x00 0x00000000 ++ 0x17 0x00000000 ++ 0x0 0xfffffffc>, ++ <0x43000000 0x04 0x00000000 ++ 0x14 0x00000000 ++ 0x3 0x00000000>; ++ ++ dma-ranges = <0x43000000 0x10 0x00000000 ++ 0x00 0x00000000 ++ 0x10 0x00000000>; ++ ++ status = "disabled"; ++ }; ++ ++ // Single-lane Gen3 PCIe ++ // Outbound window at 0x18_000000-0x1b_ffffff ++ pcie1: pcie@110000 { ++ compatible = "brcm,bcm2712-pcie"; ++ reg = <0x10 0x00110000 0x0 0x9310>; ++ device_type = "pci"; ++ max-link-speed = <2>; ++ #address-cells = <3>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ /* ++ * Unused interrupts: ++ * 218: AER ++ * 225: NMI ++ * 226: PME ++ */ ++ interrupt-parent = <&gicv2>; ++ interrupts = , ++ ; ++ interrupt-names = "pcie", "msi"; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 219 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 2 &gicv2 GIC_SPI 220 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 3 &gicv2 GIC_SPI 221 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 4 &gicv2 GIC_SPI 222 ++ IRQ_TYPE_LEVEL_HIGH>; ++ resets = <&bcm_reset 7>, <&bcm_reset 43>, <&pcie_rescal>; ++ reset-names = "swinit", "bridge", "rescal"; ++ msi-controller; ++ msi-parent = <&mip1>; ++ ++ ranges = <0x02000000 0x00 0x00000000 ++ 0x1b 0x00000000 ++ 0x00 0xfffffffc>, ++ <0x43000000 0x04 0x00000000 ++ 0x18 0x00000000 ++ 0x03 0x00000000>; ++ ++ dma-ranges = <0x03000000 0x10 0x00000000 ++ 0x00 0x00000000 ++ 0x10 0x00000000>; ++ ++ status = "disabled"; ++ }; ++ ++ pcie_rescal: reset-controller@119500 { ++ compatible = "brcm,bcm7216-pcie-sata-rescal"; ++ reg = <0x10 0x00119500 0x0 0x10>; ++ #reset-cells = <0>; ++ }; ++ ++ // Quad-lane Gen3 PCIe ++ // Outbound window at 0x1c_000000-0x1f_ffffff ++ pcie2: pcie@120000 { ++ compatible = "brcm,bcm2712-pcie"; ++ reg = <0x10 0x00120000 0x0 0x9310>; ++ device_type = "pci"; ++ max-link-speed = <2>; ++ #address-cells = <3>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ /* ++ * Unused interrupts: ++ * 228: AER ++ * 235: NMI ++ * 236: PME ++ */ ++ interrupt-parent = <&gicv2>; ++ interrupts = , ++ ; ++ interrupt-names = "pcie", "msi"; ++ interrupt-map-mask = <0x0 0x0 0x0 0x7>; ++ interrupt-map = <0 0 0 1 &gicv2 GIC_SPI 229 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 2 &gicv2 GIC_SPI 230 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 3 &gicv2 GIC_SPI 231 ++ IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 4 &gicv2 GIC_SPI 232 ++ IRQ_TYPE_LEVEL_HIGH>; ++ resets = <&bcm_reset 32>, <&bcm_reset 44>, <&pcie_rescal>; ++ reset-names = "swinit", "bridge", "rescal"; ++ msi-controller; ++ msi-parent = <&mip0>; ++ ++ // ~4GB, 32-bit, not-prefetchable at PCIe 00_00000000 ++ ranges = <0x02000000 0x00 0x00000000 ++ 0x1f 0x00000000 ++ 0x0 0xfffffffc>, ++ // 12GB, 64-bit, prefetchable at PCIe 04_00000000 ++ <0x43000000 0x04 0x00000000 ++ 0x1c 0x00000000 ++ 0x03 0x00000000>; ++ ++ // 64GB system RAM space at PCIe 10_00000000 ++ dma-ranges = <0x02000000 0x00 0x00000000 ++ 0x1f 0x00000000 ++ 0x00 0x00400000>, ++ <0x43000000 0x10 0x00000000 ++ 0x00 0x00000000 ++ 0x10 0x00000000>; ++ ++ status = "disabled"; ++ }; ++ ++ mip0: msi-controller@130000 { ++ compatible = "brcm,bcm2712-mip-intc"; ++ reg = <0x10 0x00130000 0x0 0xc0>; ++ msi-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ brcm,msi-base-spi = <128>; ++ brcm,msi-num-spis = <64>; ++ brcm,msi-offset = <0>; ++ brcm,msi-pci-addr = <0xff 0xfffff000>; ++ }; ++ ++ mip1: msi-controller@131000 { ++ compatible = "brcm,bcm2712-mip-intc"; ++ reg = <0x10 0x00131000 0x0 0xc0>; ++ msi-controller; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ brcm,msi-base-spi = <247>; ++ /* Actually 20 total, but the others are ++ * both sparse and non-consecutive */ ++ brcm,msi-num-spis = <8>; ++ brcm,msi-offset = <8>; ++ brcm,msi-pci-addr = <0xff 0xffffe000>; ++ }; ++ ++ syscon_piarbctl: syscon@400018 { ++ compatible = "brcm,syscon-piarbctl", "syscon", "simple-mfd"; ++ reg = <0x10 0x00400018 0x0 0x18>; ++ }; ++ ++ usb: usb@480000 { ++ compatible = "brcm,bcm2835-usb"; ++ reg = <0x10 0x00480000 0x0 0x10000>; ++ interrupts = ; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clocks = <&clk_usb>; ++ clock-names = "otg"; ++ phys = <&usbphy>; ++ phy-names = "usb2-phy"; ++ status = "disabled"; ++ }; ++ ++ rpivid: codec@800000 { ++ compatible = "raspberrypi,rpivid-vid-decoder"; ++ reg = <0x10 0x00800000 0x0 0x10000>, /* HEVC */ ++ <0x10 0x00840000 0x0 0x1000>; /* INTC */ ++ reg-names = "hevc", ++ "intc"; ++ ++ interrupts = ; ++ ++ clocks = <&firmware_clocks 11>; ++ clock-names = "hevc"; ++ iommus = <&iommu2>; ++ status = "disabled"; ++ }; ++ ++ sdio1: mmc@fff000 { ++ compatible = "brcm,bcm2712-sdhci"; ++ reg = <0x10 0x00fff000 0x0 0x260>, ++ <0x10 0x00fff400 0x0 0x200>, ++ <0x10 0x015040b0 0x0 0x4>, // Bus isolation control ++ <0x10 0x015200f0 0x0 0x24>; // LCPLL control misc0-8 ++ reg-names = "host", "cfg", "busisol", "lcpll"; ++ interrupts = ; ++ clocks = <&clk_emmc2>; ++ sdhci-caps-mask = <0x0000C000 0x0>; ++ sdhci-caps = <0x0 0x0>; ++ mmc-ddr-3_3v; ++ }; ++ ++ sdio2: mmc@1100000 { ++ compatible = "brcm,bcm2712-sdhci"; ++ reg = <0x10 0x01100000 0x0 0x260>, ++ <0x10 0x01100400 0x0 0x200>; ++ reg-names = "host", "cfg"; ++ interrupts = ; ++ clocks = <&clk_emmc2>; ++ sdhci-caps-mask = <0x0000C000 0x0>; ++ sdhci-caps = <0x0 0x0>; ++ supports-cqe; ++ mmc-ddr-3_3v; ++ status = "disabled"; ++ }; ++ ++ bcm_reset: reset-controller@1504318 { ++ compatible = "brcm,brcmstb-reset"; ++ reg = <0x10 0x01504318 0x0 0x30>; ++ #reset-cells = <1>; ++ }; ++ ++ v3d: v3d@2000000 { ++ compatible = "brcm,2712-v3d"; ++ reg = <0x10 0x02000000 0x0 0x4000>, ++ <0x10 0x02008000 0x0 0x6000>; ++ reg-names = "hub", "core0"; ++ ++ power-domains = <&pm BCM2835_POWER_DOMAIN_GRAFX_V3D>; ++ resets = <&pm BCM2835_RESET_V3D>; ++ clocks = <&firmware_clocks 5>; ++ clocks-names = "v3d"; ++ interrupts = , ++ ; ++ status = "disabled"; ++ }; ++ ++ gicv2: interrupt-controller@7fff9000 { ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ compatible = "arm,gic-400"; ++ reg = <0x10 0x7fff9000 0x0 0x1000>, ++ <0x10 0x7fffa000 0x0 0x2000>, ++ <0x10 0x7fffc000 0x0 0x2000>, ++ <0x10 0x7fffe000 0x0 0x2000>; ++ interrupts = ; ++ }; ++ ++ pisp_be: pisp_be@880000 { ++ compatible = "raspberrypi,pispbe"; ++ reg = <0x10 0x00880000 0x0 0x4000>; ++ interrupts = ; ++ clocks = <&firmware_clocks 7>; ++ clocks-names = "isp_be"; ++ status = "okay"; ++ iommus = <&iommu2>; ++ }; ++ }; ++ ++ clocks { ++ /* The oscillator is the root of the clock tree. */ ++ clk_osc: clk-osc { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "osc"; ++ clock-frequency = <54000000>; ++ }; ++ ++ clk_usb: clk-usb { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "otg"; ++ clock-frequency = <480000000>; ++ }; ++ ++ clk_vpu: clk_vpu { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <750000000>; ++ clock-output-names = "vpu-clock"; ++ }; ++ ++ clk_uart: clk_uart { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <9216000>; ++ clock-output-names = "uart-clock"; ++ }; ++ ++ clk_emmc2: clk_emmc2 { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <200000000>; ++ clock-output-names = "emmc2-clock"; ++ }; ++ }; ++ ++ usbphy: phy { ++ compatible = "usb-nop-xceiv"; ++ #phy-cells = <0>; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi +@@ -0,0 +1,1287 @@ ++#include ++#include ++#include ++ ++&rp1_target { ++ rp1: rp1 { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ #interrupt-cells = <2>; ++ interrupt-controller; ++ interrupt-parent = <&rp1>; ++ ++ // ranges and dma-ranges must be provided by the includer ++ ++ rp1_clocks: clocks@18000 { ++ compatible = "raspberrypi,rp1-clocks"; ++ #clock-cells = <1>; ++ reg = <0xc0 0x40018000 0x0 0x10038>; ++ clocks = <&clk_xosc>; ++ ++ assigned-clocks = <&rp1_clocks RP1_PLL_SYS_CORE>, ++ <&rp1_clocks RP1_PLL_AUDIO_CORE>, ++ // RP1_PLL_VIDEO_CORE and dividers are now managed by VEC,DPI drivers ++ <&rp1_clocks RP1_PLL_SYS>, ++ <&rp1_clocks RP1_PLL_SYS_SEC>, ++ <&rp1_clocks RP1_PLL_AUDIO>, ++ <&rp1_clocks RP1_PLL_AUDIO_SEC>, ++ <&rp1_clocks RP1_CLK_SYS>, ++ <&rp1_clocks RP1_PLL_SYS_PRI_PH>, ++ // RP1_CLK_SLOW_SYS is used for the frequency counter (FC0) ++ <&rp1_clocks RP1_CLK_SLOW_SYS>, ++ <&rp1_clocks RP1_CLK_SDIO_TIMER>, ++ <&rp1_clocks RP1_CLK_SDIO_ALT_SRC>, ++ <&rp1_clocks RP1_CLK_ETH_TSU>; ++ ++ assigned-clock-rates = <1000000000>, // RP1_PLL_SYS_CORE ++ <1536000000>, // RP1_PLL_AUDIO_CORE ++ <200000000>, // RP1_PLL_SYS ++ <125000000>, // RP1_PLL_SYS_SEC ++ <61440000>, // RP1_PLL_AUDIO ++ <192000000>, // RP1_PLL_AUDIO_SEC ++ <200000000>, // RP1_CLK_SYS ++ <100000000>, // RP1_PLL_SYS_PRI_PH ++ // Must match the XOSC frequency ++ <50000000>, // RP1_CLK_SLOW_SYS ++ <1000000>, // RP1_CLK_SDIO_TIMER ++ <200000000>, // RP1_CLK_SDIO_ALT_SRC ++ <50000000>; // RP1_CLK_ETH_TSU ++ }; ++ ++ rp1_uart0: serial@30000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40030000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ dmas = <&rp1_dma RP1_DMA_UART0_TX>, ++ <&rp1_dma RP1_DMA_UART0_RX>; ++ dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart1: serial@34000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40034000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART1_TX>, ++ // <&rp1_dma RP1_DMA_UART1_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart2: serial@38000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40038000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART2_TX>, ++ // <&rp1_dma RP1_DMA_UART2_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart3: serial@3c000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x4003c000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART3_TX>, ++ // <&rp1_dma RP1_DMA_UART3_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart4: serial@40000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40040000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART4_TX>, ++ // <&rp1_dma RP1_DMA_UART4_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_uart5: serial@44000 { ++ compatible = "arm,pl011-axi"; ++ reg = <0xc0 0x40044000 0x0 0x100>; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_UART &rp1_clocks RP1_PLL_SYS_PRI_PH>; ++ clock-names = "uartclk", "apb_pclk"; ++ // dmas = <&rp1_dma RP1_DMA_UART5_TX>, ++ // <&rp1_dma RP1_DMA_UART5_RX>; ++ // dma-names = "tx", "rx"; ++ pinctrl-names = "default"; ++ arm,primecell-periphid = <0x00541011>; ++ uart-has-rtscts; ++ cts-event-workaround; ++ skip-init; ++ status = "disabled"; ++ }; ++ ++ rp1_spi8: spi@4c000 { ++ reg = <0xc0 0x4004c000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI8_TX>, ++ <&rp1_dma RP1_DMA_SPI8_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi0: spi@50000 { ++ reg = <0xc0 0x40050000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI0_TX>, ++ <&rp1_dma RP1_DMA_SPI0_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi1: spi@54000 { ++ reg = <0xc0 0x40054000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI1_TX>, ++ <&rp1_dma RP1_DMA_SPI1_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi2: spi@58000 { ++ reg = <0xc0 0x40058000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI2_TX>, ++ <&rp1_dma RP1_DMA_SPI2_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi3: spi@5c000 { ++ reg = <0xc0 0x4005c000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI3_TX>, ++ <&rp1_dma RP1_DMA_SPI3_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ // SPI4 is a target/slave interface ++ rp1_spi4: spi@60000 { ++ reg = <0xc0 0x40060000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <0>; ++ #size-cells = <0>; ++ num-cs = <1>; ++ spi-slave; ++ dmas = <&rp1_dma RP1_DMA_SPI4_TX>, ++ <&rp1_dma RP1_DMA_SPI4_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ ++ slave { ++ compatible = "spidev"; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ ++ rp1_spi5: spi@64000 { ++ reg = <0xc0 0x40064000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI5_TX>, ++ <&rp1_dma RP1_DMA_SPI5_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_spi6: spi@68000 { ++ reg = <0xc0 0x40068000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ num-cs = <2>; ++ dmas = <&rp1_dma RP1_DMA_SPI6_TX>, ++ <&rp1_dma RP1_DMA_SPI6_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ // SPI7 is a target/slave interface ++ rp1_spi7: spi@6c000 { ++ reg = <0xc0 0x4006c000 0x0 0x130>; ++ compatible = "snps,dw-apb-ssi"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ clock-names = "ssi_clk"; ++ #address-cells = <0>; ++ #size-cells = <0>; ++ num-cs = <1>; ++ spi-slave; ++ dmas = <&rp1_dma RP1_DMA_SPI7_TX>, ++ <&rp1_dma RP1_DMA_SPI7_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ ++ slave { ++ compatible = "spidev"; ++ spi-max-frequency = <1000000>; ++ }; ++ }; ++ ++ rp1_i2c0: i2c@70000 { ++ reg = <0xc0 0x40070000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ i2c-scl-rising-time-ns = <65>; ++ i2c-scl-falling-time-ns = <100>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c1: i2c@74000 { ++ reg = <0xc0 0x40074000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ i2c-scl-rising-time-ns = <65>; ++ i2c-scl-falling-time-ns = <100>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c2: i2c@78000 { ++ reg = <0xc0 0x40078000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ i2c-scl-rising-time-ns = <65>; ++ i2c-scl-falling-time-ns = <100>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c3: i2c@7c000 { ++ reg = <0xc0 0x4007c000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ i2c-scl-rising-time-ns = <65>; ++ i2c-scl-falling-time-ns = <100>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c4: i2c@80000 { ++ reg = <0xc0 0x40080000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ i2c-scl-rising-time-ns = <65>; ++ i2c-scl-falling-time-ns = <100>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c5: i2c@84000 { ++ reg = <0xc0 0x40084000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ i2c-scl-rising-time-ns = <65>; ++ i2c-scl-falling-time-ns = <100>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2c6: i2c@88000 { ++ reg = <0xc0 0x40088000 0x0 0x1000>; ++ compatible = "snps,designware-i2c"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS>; ++ i2c-scl-rising-time-ns = <65>; ++ i2c-scl-falling-time-ns = <100>; ++ status = "disabled"; ++ }; ++ ++ rp1_pwm0: pwm@98000 { ++ compatible = "raspberrypi,rp1-pwm"; ++ reg = <0xc0 0x40098000 0x0 0x100>; ++ #pwm-cells = <3>; ++ clocks = <&rp1_clocks RP1_CLK_PWM0>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_PWM0>; ++ assigned-clock-rates = <50000000>; ++ status = "disabled"; ++ }; ++ ++ rp1_pwm1: pwm@9c000 { ++ compatible = "raspberrypi,rp1-pwm"; ++ reg = <0xc0 0x4009c000 0x0 0x100>; ++ #pwm-cells = <3>; ++ clocks = <&rp1_clocks RP1_CLK_PWM1>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_PWM1>; ++ assigned-clock-rates = <50000000>; ++ status = "disabled"; ++ }; ++ ++ rp1_i2s0: i2s@a0000 { ++ reg = <0xc0 0x400a0000 0x0 0x1000>; ++ compatible = "snps,designware-i2s"; ++ // Providing an interrupt disables DMA ++ // interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_I2S>; ++ clock-names = "i2sclk"; ++ #sound-dai-cells = <0>; ++ dmas = <&rp1_dma RP1_DMA_I2S0_TX>,<&rp1_dma RP1_DMA_I2S0_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_i2s1: i2s@a4000 { ++ reg = <0xc0 0x400a4000 0x0 0x1000>; ++ compatible = "snps,designware-i2s"; ++ // Providing an interrupt disables DMA ++ // interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_I2S>; ++ clock-names = "i2sclk"; ++ #sound-dai-cells = <0>; ++ dmas = <&rp1_dma RP1_DMA_I2S1_TX>,<&rp1_dma RP1_DMA_I2S1_RX>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ rp1_i2s2: i2s@a8000 { ++ reg = <0xc0 0x400a8000 0x0 0x1000>; ++ compatible = "snps,designware-i2s"; ++ // Providing an interrupt disables DMA ++ // interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_I2S>; ++ status = "disabled"; ++ }; ++ ++ rp1_sdio_clk0: sdio_clk0@b0004 { ++ compatible = "raspberrypi,rp1-sdio-clk"; ++ reg = <0xc0 0x400b0004 0x0 0x1c>; ++ clocks = <&sdio_src &sdhci_core>; ++ clock-names = "src", "base"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ rp1_sdio_clk1: sdio_clk1@b4004 { ++ compatible = "raspberrypi,rp1-sdio-clk"; ++ reg = <0xc0 0x400b4004 0x0 0x1c>; ++ clocks = <&sdio_src &sdhci_core>; ++ clock-names = "src", "base"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ rp1_adc: adc@c8000 { ++ compatible = "raspberrypi,rp1-adc"; ++ reg = <0xc0 0x400c8000 0x0 0x4000>; ++ clocks = <&rp1_clocks RP1_CLK_ADC>; ++ clock-names = "adcclk"; ++ #clock-cells = <0>; ++ vref-supply = <&rp1_vdd_3v3>; ++ status = "disabled"; ++ }; ++ ++ rp1_gpio: gpio@d0000 { ++ reg = <0xc0 0x400d0000 0x0 0xc000>, ++ <0xc0 0x400e0000 0x0 0xc000>, ++ <0xc0 0x400f0000 0x0 0xc000>; ++ compatible = "raspberrypi,rp1-gpio"; ++ interrupts = , ++ , ++ ; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ gpio-ranges = <&rp1_gpio 0 0 54>; ++ ++ rp1_uart0_14_15: rp1_uart0_14_15 { ++ pin_txd { ++ function = "uart0"; ++ pins = "gpio14"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart0"; ++ pins = "gpio15"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart0_ctsrts_16_17: rp1_uart0_ctsrts_16_17 { ++ pin_cts { ++ function = "uart0"; ++ pins = "gpio16"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart0"; ++ pins = "gpio17"; ++ bias-disable; ++ }; ++ }; ++ rp1_uart1_0_1: rp1_uart1_0_1 { ++ pin_txd { ++ function = "uart1"; ++ pins = "gpio0"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart1"; ++ pins = "gpio1"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart1_ctsrts_2_3: rp1_uart1_ctsrts_2_3 { ++ pin_cts { ++ function = "uart1"; ++ pins = "gpio2"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart1"; ++ pins = "gpio3"; ++ bias-disable; ++ }; ++ }; ++ rp1_uart2_4_5: rp1_uart2_4_5 { ++ pin_txd { ++ function = "uart2"; ++ pins = "gpio4"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart2"; ++ pins = "gpio5"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart2_ctsrts_6_7: rp1_uart2_ctsrts_6_7 { ++ pin_cts { ++ function = "uart2"; ++ pins = "gpio6"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart2"; ++ pins = "gpio7"; ++ bias-disable; ++ }; ++ }; ++ rp1_uart3_8_9: rp1_uart3_8_9 { ++ pin_txd { ++ function = "uart3"; ++ pins = "gpio8"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart3"; ++ pins = "gpio9"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart3_ctsrts_10_11: rp1_uart3_ctsrts_10_11 { ++ pin_cts { ++ function = "uart3"; ++ pins = "gpio10"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart3"; ++ pins = "gpio11"; ++ bias-disable; ++ }; ++ }; ++ rp1_uart4_12_13: rp1_uart4_12_13 { ++ pin_txd { ++ function = "uart4"; ++ pins = "gpio12"; ++ bias-disable; ++ }; ++ pin_rxd { ++ function = "uart4"; ++ pins = "gpio13"; ++ bias-pull-up; ++ }; ++ }; ++ rp1_uart4_ctsrts_14_15: rp1_uart4_ctsrts_14_15 { ++ pin_cts { ++ function = "uart4"; ++ pins = "gpio14"; ++ bias-pull-up; ++ }; ++ pin_rts { ++ function = "uart4"; ++ pins = "gpio15"; ++ bias-disable; ++ }; ++ }; ++ ++ rp1_sdio0_22_27: rp1_sdio0_22_27 { ++ pin_clk { ++ function = "sd0"; ++ pins = "gpio22"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ pin_cmd { ++ function = "sd0"; ++ pins = "gpio23"; ++ bias-pull-up; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ pins_dat { ++ function = "sd0"; ++ pins = "gpio24", "gpio25", "gpio26", "gpio27"; ++ bias-pull-up; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ }; ++ ++ rp1_sdio1_28_33: rp1_sdio1_28_33 { ++ pin_clk { ++ function = "sd1"; ++ pins = "gpio28"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ pin_cmd { ++ function = "sd1"; ++ pins = "gpio29"; ++ bias-pull-up; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ pins_dat { ++ function = "sd1"; ++ pins = "gpio30", "gpio31", "gpio32", "gpio33"; ++ bias-pull-up; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ }; ++ ++ rp1_i2s0_18_21: rp1_i2s0_18_21 { ++ function = "i2s0"; ++ pins = "gpio18", "gpio19", "gpio20", "gpio21"; ++ bias-disable; ++ }; ++ ++ rp1_i2s1_18_21: rp1_i2s1_18_21 { ++ function = "i2s1"; ++ pins = "gpio18", "gpio19", "gpio20", "gpio21"; ++ bias-disable; ++ }; ++ ++ rp1_i2c4_34_35: rp1_i2c4_34_35 { ++ function = "i2c4"; ++ pins = "gpio34", "gpio35"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c6_38_39: rp1_i2c6_38_39 { ++ function = "i2c6"; ++ pins = "gpio38", "gpio39"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c4_40_41: rp1_i2c4_40_41 { ++ function = "i2c4"; ++ pins = "gpio40", "gpio41"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c5_44_45: rp1_i2c5_44_45 { ++ function = "i2c5"; ++ pins = "gpio44", "gpio45"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c0_0_1: rp1_i2c0_0_1 { ++ function = "i2c0"; ++ pins = "gpio0", "gpio1"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c0_8_9: rp1_i2c0_8_9 { ++ function = "i2c0"; ++ pins = "gpio8", "gpio9"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c1_2_3: rp1_i2c1_2_3 { ++ function = "i2c1"; ++ pins = "gpio2", "gpio3"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c1_10_11: rp1_i2c1_10_11 { ++ function = "i2c1"; ++ pins = "gpio10", "gpio11"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c2_4_5: rp1_i2c2_4_5 { ++ function = "i2c2"; ++ pins = "gpio4", "gpio5"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c2_12_13: rp1_i2c2_12_13 { ++ function = "i2c2"; ++ pins = "gpio12", "gpio13"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c3_6_7: rp1_i2c3_6_7 { ++ function = "i2c3"; ++ pins = "gpio6", "gpio7"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c3_14_15: rp1_i2c3_14_15 { ++ function = "i2c3"; ++ pins = "gpio14", "gpio15"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ rp1_i2c3_22_23: rp1_i2c3_22_23 { ++ function = "i2c3"; ++ pins = "gpio22", "gpio23"; ++ drive-strength = <12>; ++ bias-pull-up; ++ }; ++ ++ // DPI mappings with HSYNC,VSYNC but without PIXCLK,DE ++ rp1_dpi_16bit_gpio2: rp1_dpi_16bit_gpio2 { /* Mode 2, not fully supported by RP1 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", "gpio9", ++ "gpio10", "gpio11", "gpio12", "gpio13", ++ "gpio14", "gpio15", "gpio16", "gpio17", ++ "gpio18", "gpio19"; ++ bias-disable; ++ }; ++ rp1_dpi_16bit_cpadhi_gpio2: rp1_dpi_16bit_cpadhi_gpio2 { /* Mode 3 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24"; ++ bias-disable; ++ }; ++ rp1_dpi_16bit_pad666_gpio2: rp1_dpi_16bit_pad666_gpio2 { /* Mode 4 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", ++ "gpio5", "gpio6", "gpio7", "gpio8", ++ "gpio9", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio21", "gpio22", "gpio23", "gpio24", ++ "gpio25"; ++ bias-disable; ++ }; ++ rp1_dpi_18bit_gpio2: rp1_dpi_18bit_gpio2 { /* Mode 5, not fully supported by RP1 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", "gpio9", ++ "gpio10", "gpio11", "gpio12", "gpio13", ++ "gpio14", "gpio15", "gpio16", "gpio17", ++ "gpio18", "gpio19", "gpio20", "gpio21"; ++ bias-disable; ++ }; ++ rp1_dpi_18bit_cpadhi_gpio2: rp1_dpi_18bit_cpadhi_gpio2 { /* Mode 6 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", "gpio9", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24", "gpio25"; ++ bias-disable; ++ }; ++ rp1_dpi_24bit_gpio2: rp1_dpi_24bit_gpio2 { /* Mode 7 */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3", "gpio4", "gpio5", ++ "gpio6", "gpio7", "gpio8", "gpio9", ++ "gpio10", "gpio11", "gpio12", "gpio13", ++ "gpio14", "gpio15", "gpio16", "gpio17", ++ "gpio18", "gpio19", "gpio20", "gpio21", ++ "gpio22", "gpio23", "gpio24", "gpio25", ++ "gpio26", "gpio27"; ++ bias-disable; ++ }; ++ rp1_dpi_hvsync: rp1_dpi_hvsync { /* Sync only, for use with int VDAC */ ++ function = "dpi"; ++ pins = "gpio2", "gpio3"; ++ bias-disable; ++ }; ++ ++ // More DPI mappings, including PIXCLK,DE on GPIOs 0,1 ++ rp1_dpi_16bit_gpio0: rp1_dpi_16bit_gpio0 { /* Mode 2, not fully supported by RP1 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", "gpio9", "gpio10", "gpio11", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", "gpio18", "gpio19"; ++ bias-disable; ++ }; ++ rp1_dpi_16bit_cpadhi_gpio0: rp1_dpi_16bit_cpadhi_gpio0 { /* Mode 3 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24"; ++ bias-disable; ++ }; ++ rp1_dpi_16bit_pad666_gpio0: rp1_dpi_16bit_pad666_gpio0 { /* Mode 4 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio5", "gpio6", "gpio7", "gpio8", ++ "gpio9", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio21", "gpio22", "gpio23", "gpio24", ++ "gpio25"; ++ bias-disable; ++ }; ++ rp1_dpi_18bit_gpio0: rp1_dpi_18bit_gpio0 { /* Mode 5, not fully supported by RP1 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", "gpio9", "gpio10", "gpio11", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", "gpio18", "gpio19", ++ "gpio20", "gpio21"; ++ bias-disable; ++ }; ++ rp1_dpi_18bit_cpadhi_gpio0: rp1_dpi_18bit_cpadhi_gpio0 { /* Mode 6 */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", "gpio9", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24", "gpio25"; ++ bias-disable; ++ }; ++ rp1_dpi_24bit_gpio0: rp1_dpi_24bit_gpio0 { /* Mode 7 -- All GPIOs used! */ ++ function = "dpi"; ++ pins = "gpio0", "gpio1", "gpio2", "gpio3", ++ "gpio4", "gpio5", "gpio6", "gpio7", ++ "gpio8", "gpio9", "gpio10", "gpio11", ++ "gpio12", "gpio13", "gpio14", "gpio15", ++ "gpio16", "gpio17", "gpio18", "gpio19", ++ "gpio20", "gpio21", "gpio22", "gpio23", ++ "gpio24", "gpio25", "gpio26", "gpio27"; ++ bias-disable; ++ }; ++ ++ rp1_gpclksrc0_gpio4: rp1_gpclksrc0_gpio4 { ++ function = "gpclk0"; ++ pins = "gpio4"; ++ bias-disable; ++ }; ++ ++ rp1_gpclksrc0_gpio20: rp1_gpclksrc0_gpio20 { ++ function = "gpclk0"; ++ pins = "gpio20"; ++ bias-disable; ++ }; ++ ++ rp1_gpclksrc1_gpio5: rp1_gpclksrc1_gpio5 { ++ function = "gpclk1"; ++ pins = "gpio5"; ++ bias-disable; ++ }; ++ ++ rp1_gpclksrc1_gpio18: rp1_gpclksrc1_gpio18 { ++ function = "gpclk1"; ++ pins = "gpio18"; ++ bias-disable; ++ }; ++ ++ rp1_gpclksrc1_gpio21: rp1_gpclksrc1_gpio21 { ++ function = "gpclk1"; ++ pins = "gpio21"; ++ bias-disable; ++ }; ++ ++ rp1_pwm1_gpio45: rp1_pwm1_gpio45 { ++ function = "pwm1"; ++ pins = "gpio45"; ++ bias-pull-down; ++ }; ++ ++ rp1_spi0_gpio9: rp1_spi0_gpio9 { ++ function = "spi0"; ++ pins = "gpio9", "gpio10", "gpio11"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi0_cs_gpio7: rp1_spi0_cs_gpio7 { ++ function = "spi0"; ++ pins = "gpio7", "gpio8"; ++ bias-pull-up; ++ }; ++ ++ rp1_spi1_gpio19: rp1_spi1_gpio19 { ++ function = "spi1"; ++ pins = "gpio19", "gpio20", "gpio21"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi2_gpio1: rp1_spi2_gpio1 { ++ function = "spi2"; ++ pins = "gpio1", "gpio2", "gpio3"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi3_gpio5: rp1_spi3_gpio5 { ++ function = "spi3"; ++ pins = "gpio5", "gpio6", "gpio7"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi4_gpio9: rp1_spi4_gpio9 { ++ function = "spi4"; ++ pins = "gpio9", "gpio10", "gpio11"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi5_gpio13: rp1_spi5_gpio13 { ++ function = "spi5"; ++ pins = "gpio13", "gpio14", "gpio15"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi8_gpio49: rp1_spi8_gpio49 { ++ function = "spi8"; ++ pins = "gpio49", "gpio50", "gpio51"; ++ bias-disable; ++ drive-strength = <12>; ++ slew-rate = <1>; ++ }; ++ ++ rp1_spi8_cs_gpio52: rp1_spi8_cs_gpio52 { ++ function = "spi0"; ++ pins = "gpio52", "gpio53"; ++ bias-pull-up; ++ }; ++ }; ++ ++ rp1_eth: ethernet@100000 { ++ reg = <0xc0 0x40100000 0x0 0x4000>; ++ compatible = "cdns,macb"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupts = ; ++ clocks = <&macb_pclk &macb_hclk &rp1_clocks RP1_CLK_ETH_TSU>; ++ clock-names = "pclk", "hclk", "tsu_clk"; ++ phy-mode = "rgmii-id"; ++ cdns,aw2w-max-pipe = /bits/ 8 <8>; ++ cdns,ar2r-max-pipe = /bits/ 8 <8>; ++ cdns,use-aw2b-fill; ++ local-mac-address = [00 00 00 00 00 00]; ++ status = "disabled"; ++ }; ++ ++ rp1_csi0: csi@110000 { ++ compatible = "raspberrypi,rp1-cfe"; ++ reg = <0xc0 0x40110000 0x0 0x100>, // CSI2 DMA address ++ <0xc0 0x40114000 0x0 0x100>, // PHY/CSI Host address ++ <0xc0 0x40120000 0x0 0x100>, // MIPI CFG address ++ <0xc0 0x40124000 0x0 0x1000>; // PiSP FE address ++ ++ // interrupts must match rp1_pisp_fe setup ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; ++ assigned-clock-rates = <25000000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ rp1_csi1: csi@128000 { ++ compatible = "raspberrypi,rp1-cfe"; ++ reg = <0xc0 0x40128000 0x0 0x100>, // CSI2 DMA address ++ <0xc0 0x4012c000 0x0 0x100>, // PHY/CSI Host address ++ <0xc0 0x40138000 0x0 0x100>, // MIPI CFG address ++ <0xc0 0x4013c000 0x0 0x1000>; // PiSP FE address ++ ++ // interrupts must match rp1_pisp_fe setup ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; ++ assigned-clock-rates = <25000000>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ rp1_mmc0: mmc@180000 { ++ reg = <0xc0 0x40180000 0x0 0x100>; ++ compatible = "raspberrypi,rp1-dwcmshc"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core ++ &rp1_clocks RP1_CLK_SDIO_TIMER ++ &rp1_sdio_clk0>; ++ clock-names = "bus", "core", "timeout", "sdio"; ++ /* Bank 0 VDDIO is fixed */ ++ no-1-8-v; ++ bus-width = <4>; ++ vmmc-supply = <&rp1_vdd_3v3>; ++ broken-cd; ++ status = "disabled"; ++ }; ++ ++ rp1_mmc1: mmc@184000 { ++ reg = <0xc0 0x40184000 0x0 0x100>; ++ compatible = "raspberrypi,rp1-dwcmshc"; ++ interrupts = ; ++ clocks = <&rp1_clocks RP1_CLK_SYS &sdhci_core ++ &rp1_clocks RP1_CLK_SDIO_TIMER ++ &rp1_sdio_clk1>; ++ clock-names = "bus", "core", "timeout", "sdio"; ++ bus-width = <4>; ++ vmmc-supply = <&rp1_vdd_3v3>; ++ /* Nerf SDR speeds */ ++ sdhci-caps-mask = <0x3 0x0>; ++ broken-cd; ++ status = "disabled"; ++ }; ++ ++ rp1_dma: dma@188000 { ++ reg = <0xc0 0x40188000 0x0 0x1000>; ++ compatible = "snps,axi-dma-1.01a"; ++ interrupts = ; ++ clocks = <&sdhci_core &rp1_clocks RP1_CLK_SYS>; ++ clock-names = "core-clk", "cfgr-clk"; ++ ++ #dma-cells = <1>; ++ dma-channels = <8>; ++ snps,dma-masters = <1>; ++ snps,dma-targets = <64>; ++ snps,data-width = <4>; // (8 << 4) == 128 bits ++ snps,block-size = <0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000>; ++ snps,priority = <0 1 2 3 4 5 6 7>; ++ snps,axi-max-burst-len = <8>; ++ status = "disabled"; ++ }; ++ ++ rp1_usb0: usb@200000 { ++ reg = <0xc0 0x40200000 0x0 0x100000>; ++ compatible = "snps,dwc3"; ++ dr_mode = "host"; ++ usb3-lpm-capable; ++ snps,axi-pipe-limit = /bits/ 8 <8>; ++ snps,dis_rxdet_inp3_quirk; ++ snps,parkmode-disable-ss-quirk; ++ snps,parkmode-disable-hs-quirk; ++ snps,parkmode-disable-fsls-quirk; ++ snps,tx-max-burst = /bits/ 8 <8>; ++ snps,tx-thr-num-pkt = /bits/ 8 <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ rp1_usb1: usb@300000 { ++ reg = <0xc0 0x40300000 0x0 0x100000>; ++ compatible = "snps,dwc3"; ++ dr_mode = "host"; ++ usb3-lpm-capable; ++ snps,axi-pipe-limit = /bits/ 8 <8>; ++ snps,dis_rxdet_inp3_quirk; ++ snps,parkmode-disable-ss-quirk; ++ snps,parkmode-disable-hs-quirk; ++ snps,parkmode-disable-fsls-quirk; ++ snps,tx-max-burst = /bits/ 8 <8>; ++ snps,tx-thr-num-pkt = /bits/ 8 <2>; ++ interrupts = ; ++ status = "disabled"; ++ }; ++ ++ rp1_dsi0: dsi@110000 { ++ compatible = "raspberrypi,rp1dsi"; ++ status = "disabled"; ++ reg = <0xc0 0x40118000 0x0 0x1000>, // MIPI0 DSI DMA (ArgonDPI) ++ <0xc0 0x4011c000 0x0 0x1000>, // MIPI0 DSI Host (SNPS) ++ <0xc0 0x40120000 0x0 0x1000>; // MIPI0 CFG ++ ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>, ++ <&rp1_clocks RP1_CLK_MIPI0_DPI>, ++ <&rp1_clocks RP1_CLK_MIPI0_DSI_BYTECLOCK>, ++ <&clk_xosc>, // hardwired to DSI "refclk" ++ <&rp1_clocks RP1_PLL_SYS>; // alternate parent for divide ++ clock-names = "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys"; ++ ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI0_CFG>; ++ assigned-clock-rates = <25000000>; ++ }; ++ ++ rp1_dsi1: dsi@128000 { ++ compatible = "raspberrypi,rp1dsi"; ++ status = "disabled"; ++ reg = <0xc0 0x40130000 0x0 0x1000>, // MIPI1 DSI DMA (ArgonDPI) ++ <0xc0 0x40134000 0x0 0x1000>, // MIPI1 DSI Host (SNPS) ++ <0xc0 0x40138000 0x0 0x1000>; // MIPI1 CFG ++ ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>, ++ <&rp1_clocks RP1_CLK_MIPI1_DPI>, ++ <&rp1_clocks RP1_CLK_MIPI1_DSI_BYTECLOCK>, ++ <&clk_xosc>, // hardwired to DSI "refclk" ++ <&rp1_clocks RP1_PLL_SYS>; // alternate parent for divide ++ clock-names = "cfgclk", "dpiclk", "byteclk", "refclk", "pllsys"; ++ ++ assigned-clocks = <&rp1_clocks RP1_CLK_MIPI1_CFG>; ++ assigned-clock-rates = <25000000>; ++ }; ++ ++ /* VEC and DPI both need to control PLL_VIDEO and cannot work together; */ ++ /* config.txt should enable one or other using dtparam=vec or an overlay. */ ++ rp1_vec: vec@144000 { ++ compatible = "raspberrypi,rp1vec"; ++ status = "disabled"; ++ reg = <0xc0 0x40144000 0x0 0x1000>, // VIDEO_OUT_VEC ++ <0xc0 0x40140000 0x0 0x1000>; // VIDEO_OUT_CFG ++ ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_VEC>; ++ ++ assigned-clocks = <&rp1_clocks RP1_PLL_VIDEO_CORE>, ++ <&rp1_clocks RP1_PLL_VIDEO_SEC>, ++ <&rp1_clocks RP1_CLK_VEC>; ++ assigned-clock-rates = <1188000000>, ++ <108000000>, ++ <108000000>; ++ assigned-clock-parents = <0>, ++ <&rp1_clocks RP1_PLL_VIDEO_CORE>, ++ <&rp1_clocks RP1_PLL_VIDEO_SEC>; ++ }; ++ ++ rp1_dpi: dpi@148000 { ++ compatible = "raspberrypi,rp1dpi"; ++ status = "disabled"; ++ reg = <0xc0 0x40148000 0x0 0x1000>, // VIDEO_OUT DPI ++ <0xc0 0x40140000 0x0 0x1000>; // VIDEO_OUT_CFG ++ ++ interrupts = ; ++ ++ clocks = <&rp1_clocks RP1_CLK_DPI>, // DPI pixel clock ++ <&rp1_clocks RP1_PLL_VIDEO>, // PLL primary divider, and ++ <&rp1_clocks RP1_PLL_VIDEO_CORE>; // VCO, which we also control ++ clock-names = "dpiclk", "plldiv", "pllcore"; ++ ++ assigned-clocks = <&rp1_clocks RP1_CLK_DPI>; ++ assigned-clock-parents = <&rp1_clocks RP1_PLL_VIDEO>; ++ }; ++ }; ++}; ++ ++&clocks { ++ clk_xosc: clk_xosc { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "xosc"; ++ clock-frequency = <50000000>; ++ }; ++ macb_pclk: macb_pclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "pclk"; ++ clock-frequency = <200000000>; ++ }; ++ macb_hclk: macb_hclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "hclk"; ++ clock-frequency = <200000000>; ++ }; ++ sdio_src: sdio_src { ++ // 400 MHz on FPGA. PLL sys VCO on asic ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "src"; ++ clock-frequency = <1000000000>; ++ }; ++ sdhci_core: sdhci_core { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-output-names = "core"; ++ clock-frequency = <50000000>; ++ }; ++ /* GPIO derived clock sources. Each GPIO with a GPCLK function ++ * can drive its output from the respective GPCLK ++ * generator, and provide a clock source to other internal ++ * dividers. Add dummy sources here so that they can be overridden ++ * with overlays. ++ */ ++ clksrc_gp0: clksrc_gp0 { ++ status = "disabled"; ++ compatible = "fixed-factor-clock"; ++ #clock-cells = <0>; ++ clock-div = <1>; ++ clock-mult = <1>; ++ clocks = <&rp1_clocks RP1_CLK_GP0>; ++ clock-output-names = "clksrc_gp0"; ++ }; ++ clksrc_gp1: clksrc_gp1 { ++ status = "disabled"; ++ compatible = "fixed-factor-clock"; ++ #clock-cells = <0>; ++ clock-div = <1>; ++ clock-mult = <1>; ++ clocks = <&rp1_clocks RP1_CLK_GP1>; ++ clock-output-names = "clksrc_gp1"; ++ }; ++ clksrc_gp2: clksrc_gp2 { ++ status = "disabled"; ++ compatible = "fixed-factor-clock"; ++ clock-div = <1>; ++ clock-mult = <1>; ++ #clock-cells = <0>; ++ clocks = <&rp1_clocks RP1_CLK_GP2>; ++ clock-output-names = "clksrc_gp2"; ++ }; ++ clksrc_gp3: clksrc_gp3 { ++ status = "disabled"; ++ compatible = "fixed-factor-clock"; ++ clock-div = <1>; ++ clock-mult = <1>; ++ #clock-cells = <0>; ++ clocks = <&rp1_clocks RP1_CLK_GP3>; ++ clock-output-names = "clksrc_gp3"; ++ }; ++ clksrc_gp4: clksrc_gp4 { ++ status = "disabled"; ++ compatible = "fixed-factor-clock"; ++ #clock-cells = <0>; ++ clock-div = <1>; ++ clock-mult = <1>; ++ clocks = <&rp1_clocks RP1_CLK_GP4>; ++ clock-output-names = "clksrc_gp4"; ++ }; ++ clksrc_gp5: clksrc_gp5 { ++ status = "disabled"; ++ compatible = "fixed-factor-clock"; ++ #clock-cells = <0>; ++ clock-div = <1>; ++ clock-mult = <1>; ++ clocks = <&rp1_clocks RP1_CLK_GP5>; ++ clock-output-names = "clksrc_gp5"; ++ }; ++}; ++ ++/ { ++ rp1_vdd_3v3: rp1_vdd_3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd-3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ }; ++}; diff --git a/target/linux/bcm27xx/patches-6.6/950-1181-arm64-dts-Add-cm5l-files.patch b/target/linux/bcm27xx/patches-6.6/950-1181-arm64-dts-Add-cm5l-files.patch new file mode 100644 index 0000000000..4f0544386a --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1181-arm64-dts-Add-cm5l-files.patch @@ -0,0 +1,92 @@ +From 4de4f56af7d803fa7dd9ffe42d4719b428d73e6c Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 17 Jul 2024 17:31:58 +0100 +Subject: [PATCH 1181/1215] arm64: dts: Add cm5l files + +CM5 Lite DTBs require minor changes compared to the "heavy" variants. + +Signed-off-by: Phil Elwell +--- + arch/arm64/boot/dts/broadcom/Makefile | 2 ++ + .../dts/broadcom/bcm2712-rpi-cm5l-cm4io.dts | 20 ++++++++++++++++ + .../dts/broadcom/bcm2712-rpi-cm5l-cm5io.dts | 10 ++++++++ + .../boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi | 24 +++++++++++++++++++ + 4 files changed, 56 insertions(+) + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l-cm4io.dts + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l-cm5io.dts + create mode 100644 arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi + +--- a/arch/arm64/boot/dts/broadcom/Makefile ++++ b/arch/arm64/boot/dts/broadcom/Makefile +@@ -24,6 +24,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rp + dtb-$(CONFIG_ARCH_BCM2835) += bcm2712d0-rpi-5-b.dtb + dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-cm5-cm5io.dtb + dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-cm5-cm4io.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-cm5l-cm5io.dtb ++dtb-$(CONFIG_ARCH_BCM2835) += bcm2712-rpi-cm5l-cm4io.dtb + + subdir-y += bcmbca + subdir-y += northstar2 +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l-cm4io.dts +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/dts-v1/; ++ ++#include "bcm2712-rpi-cm5l.dtsi" ++ ++// The RP1 USB3 interfaces are not usable on CM4IO ++ ++&rp1_usb0 { ++ status = "disabled"; ++}; ++ ++&rp1_usb1 { ++ status = "disabled"; ++}; ++ ++/ { ++ __overrides__ { ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l-cm5io.dts +@@ -0,0 +1,10 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/dts-v1/; ++ ++#include "bcm2712-rpi-cm5l.dtsi" ++ ++/ { ++ __overrides__ { ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ }; ++}; +--- /dev/null ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/dts-v1/; ++ ++#include "bcm2712-rpi-cm5.dtsi" ++ ++/ { ++ __overrides__ { ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ }; ++}; ++ ++&sd_io_1v8_reg { ++ compatible = "regulator-gpio"; ++ regulator-max-microvolt = <3300000>; ++ regulator-settling-time-us = <5000>; ++ gpios = <&gio_aon 3 GPIO_ACTIVE_HIGH>; ++ states = <1800000 0x1 ++ 3300000 0x0>; ++}; ++ ++&sdio1 { ++ /delete-property/ mmc-hs400-1_8v; ++ /delete-property/ mmc-hs400-enhanced-strobe; ++}; diff --git a/target/linux/bcm27xx/patches-6.6/950-1182-dts-bcm2712-Dedup-the-aliases-and-overrides.patch b/target/linux/bcm27xx/patches-6.6/950-1182-dts-bcm2712-Dedup-the-aliases-and-overrides.patch new file mode 100644 index 0000000000..6cffbdd9be --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1182-dts-bcm2712-Dedup-the-aliases-and-overrides.patch @@ -0,0 +1,408 @@ +From e1c56acf3355cd539447511fdc1b886e5eb5cca3 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 May 2024 16:57:31 +0100 +Subject: [PATCH 1182/1215] dts: bcm2712: Dedup the aliases and overrides + +Move the aliases and overrrides shared by Pi 5 and CM5 into +bcm2712-rpi.dtsi. + +Signed-off-by: Phil Elwell +--- + .../boot/dts/broadcom/bcm2712-rpi-5-b.dts | 115 ----------------- + .../boot/dts/broadcom/bcm2712-rpi-cm5.dtsi | 114 ----------------- + arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 117 +++++++++++++++++- + 3 files changed, 113 insertions(+), 233 deletions(-) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +@@ -746,122 +746,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + }; + + / { +- aliases: aliases { +- blconfig = &blconfig; +- blpubkey = &blpubkey; +- bluetooth = &bluetooth; +- console = &uart10; +- ethernet0 = &rp1_eth; +- wifi0 = &wifi; +- fb = &fb; +- mailbox = &mailbox; +- mmc0 = &sdio1; +- uart0 = &uart0; +- uart1 = &uart1; +- uart2 = &uart2; +- uart3 = &uart3; +- uart4 = &uart4; +- uart10 = &uart10; +- serial0 = &uart0; +- serial1 = &uart1; +- serial2 = &uart2; +- serial3 = &uart3; +- serial4 = &uart4; +- serial10 = &uart10; +- i2c = &i2c_arm; +- i2c0 = &i2c0; +- i2c1 = &i2c1; +- i2c2 = &i2c2; +- i2c3 = &i2c3; +- i2c4 = &i2c4; +- i2c5 = &i2c5; +- i2c6 = &i2c6; +- i2c10 = &i2c_rp1boot; +- // Bit-bashed i2c_gpios start at 10 +- spi0 = &spi0; +- spi1 = &spi1; +- spi2 = &spi2; +- spi3 = &spi3; +- spi4 = &spi4; +- spi5 = &spi5; +- spi10 = &spi10; +- gpio0 = &gpio; +- gpio1 = &gio; +- gpio2 = &gio_aon; +- gpio3 = &pinctrl; +- gpio4 = &pinctrl_aon; +- usb0 = &rp1_usb0; +- usb1 = &rp1_usb1; +- drm-dsi1 = &dsi0; +- drm-dsi2 = &dsi1; +- }; +- + __overrides__ { +- bdaddr = <&bluetooth>, "local-bd-address["; +- button_debounce = <&pwr_key>, "debounce-interval:0"; +- cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status"; +- uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0; +- i2c0 = <&i2c0>, "status"; +- i2c1 = <&i2c1>, "status"; +- i2c = <&i2c1>, "status"; +- i2c_arm = <&i2c_arm>, "status"; +- i2c_vc = <&i2c_vc>, "status"; +- i2c_csi_dsi = <&i2c_csi_dsi>, "status"; +- i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status"; +- i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status"; +- i2c0_baudrate = <&i2c0>, "clock-frequency:0"; +- i2c1_baudrate = <&i2c1>, "clock-frequency:0"; +- i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; +- i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; +- i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; +- krnbt = <&bluetooth>, "status"; +- nvme = <&pciex1>, "status"; +- pciex1 = <&pciex1>, "status"; +- pciex1_gen = <&pciex1> , "max-link-speed:0"; +- pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; +- pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; +- pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; +- random = <&random>, "status"; +- rtc = <&rpi_rtc>, "status"; +- rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; + sd_cqe = <&sdio1>, "supports-cqe?"; +- spi = <&spi0>, "status"; +- suspend = <&pwr_key>, "linux,code:0=205"; +- uart0 = <&uart0>, "status"; +- wifiaddr = <&wifi>, "local-mac-address["; +- +- act_led_gpio = <&led_act>,"gpios:4",<&led_act>,"gpios:0=",<&gpio>; +- act_led_activelow = <&led_act>,"gpios:8"; +- act_led_trigger = <&led_act>, "linux,default-trigger"; +- pwr_led_gpio = <&led_pwr>,"gpios:4"; +- pwr_led_activelow = <&led_pwr>, "gpios:8"; +- pwr_led_trigger = <&led_pwr>, "linux,default-trigger"; +- eth_led0 = <&phy1>,"led-modes:0"; +- eth_led1 = <&phy1>,"led-modes:4"; +- drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; +- drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; +- drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; +- drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; +- drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0; +- drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1; +- drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi; +- drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; +- drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0; +- drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; +- drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; +- drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; +- +- fan_temp0 = <&cpu_tepid>,"temperature:0"; +- fan_temp1 = <&cpu_warm>,"temperature:0"; +- fan_temp2 = <&cpu_hot>,"temperature:0"; +- fan_temp3 = <&cpu_vhot>,"temperature:0"; +- fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0"; +- fan_temp1_hyst = <&cpu_warm>,"hysteresis:0"; +- fan_temp2_hyst = <&cpu_hot>,"hysteresis:0"; +- fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0"; +- fan_temp0_speed = <&fan>, "cooling-levels:4"; +- fan_temp1_speed = <&fan>, "cooling-levels:8"; +- fan_temp2_speed = <&fan>, "cooling-levels:12"; +- fan_temp3_speed = <&fan>, "cooling-levels:16"; + }; + }; +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5.dtsi +@@ -753,108 +753,7 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + }; + + / { +- aliases: aliases { +- blconfig = &blconfig; +- blpubkey = &blpubkey; +- bluetooth = &bluetooth; +- console = &uart10; +- ethernet0 = &rp1_eth; +- wifi0 = &wifi; +- fb = &fb; +- mailbox = &mailbox; +- mmc0 = &sdio1; +- uart0 = &uart0; +- uart1 = &uart1; +- uart2 = &uart2; +- uart3 = &uart3; +- uart4 = &uart4; +- uart10 = &uart10; +- serial0 = &uart0; +- serial1 = &uart1; +- serial2 = &uart2; +- serial3 = &uart3; +- serial4 = &uart4; +- serial10 = &uart10; +- i2c = &i2c_arm; +- i2c0 = &i2c0; +- i2c1 = &i2c1; +- i2c2 = &i2c2; +- i2c3 = &i2c3; +- i2c4 = &i2c4; +- i2c5 = &i2c5; +- i2c6 = &i2c6; +- i2c10 = &i2c_rp1boot; +- // Bit-bashed i2c_gpios start at 10 +- spi0 = &spi0; +- spi1 = &spi1; +- spi2 = &spi2; +- spi3 = &spi3; +- spi4 = &spi4; +- spi5 = &spi5; +- spi10 = &spi10; +- gpio0 = &gpio; +- gpio1 = &gio; +- gpio2 = &gio_aon; +- gpio3 = &pinctrl; +- gpio4 = &pinctrl_aon; +- usb0 = &rp1_usb0; +- usb1 = &rp1_usb1; +- drm-dsi1 = &dsi0; +- drm-dsi2 = &dsi1; +- }; +- + __overrides__ { +- bdaddr = <&bluetooth>, "local-bd-address["; +- button_debounce = <&pwr_key>, "debounce-interval:0"; +- cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status"; +- uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0; +- i2c0 = <&i2c0>, "status"; +- i2c1 = <&i2c1>, "status"; +- i2c = <&i2c1>, "status"; +- i2c_arm = <&i2c_arm>, "status"; +- i2c_vc = <&i2c_vc>, "status"; +- i2c_csi_dsi = <&i2c_csi_dsi>, "status"; +- i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status"; +- i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status"; +- i2c0_baudrate = <&i2c0>, "clock-frequency:0"; +- i2c1_baudrate = <&i2c1>, "clock-frequency:0"; +- i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; +- i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; +- i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; +- krnbt = <&bluetooth>, "status"; +- nvme = <&pciex1>, "status"; +- pciex1 = <&pciex1>, "status"; +- pciex1_gen = <&pciex1> , "max-link-speed:0"; +- pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; +- pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; +- pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; +- random = <&random>, "status"; +- rtc = <&rpi_rtc>, "status"; +- rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; +- spi = <&spi0>, "status"; +- suspend = <&pwr_key>, "linux,code:0=205"; +- uart0 = <&uart0>, "status"; +- wifiaddr = <&wifi>, "local-mac-address["; +- +- act_led_activelow = <&led_act>, "active-low?"; +- act_led_trigger = <&led_act>, "linux,default-trigger"; +- pwr_led_activelow = <&led_pwr>, "gpios:8"; +- pwr_led_trigger = <&led_pwr>, "linux,default-trigger"; +- eth_led0 = <&phy1>,"led-modes:0"; +- eth_led1 = <&phy1>,"led-modes:4"; +- drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; +- drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; +- drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; +- drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; +- drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0; +- drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1; +- drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi; +- drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; +- drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0; +- drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; +- drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; +- drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; +- + ant1 = <&ant1>,"output-high?=on", + <&ant1>, "output-low?=off", + <&ant2>, "output-high?=off", +@@ -867,18 +766,5 @@ spi10_cs_pins: &spi10_cs_gpio1 {}; + <&ant1>, "output-low?=on", + <&ant2>, "output-high?=off", + <&ant2>, "output-low?=on"; +- +- fan_temp0 = <&cpu_tepid>,"temperature:0"; +- fan_temp1 = <&cpu_warm>,"temperature:0"; +- fan_temp2 = <&cpu_hot>,"temperature:0"; +- fan_temp3 = <&cpu_vhot>,"temperature:0"; +- fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0"; +- fan_temp1_hyst = <&cpu_warm>,"hysteresis:0"; +- fan_temp2_hyst = <&cpu_hot>,"hysteresis:0"; +- fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0"; +- fan_temp0_speed = <&fan>, "cooling-levels:4"; +- fan_temp1_speed = <&fan>, "cooling-levels:8"; +- fan_temp2_speed = <&fan>, "cooling-levels:12"; +- fan_temp3_speed = <&fan>, "cooling-levels:16"; + }; + }; +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi +@@ -98,14 +98,124 @@ + }; + + / { ++ aliases: aliases { ++ blconfig = &blconfig; ++ blpubkey = &blpubkey; ++ bluetooth = &bluetooth; ++ console = &uart10; ++ drm-dsi1 = &dsi0; ++ drm-dsi2 = &dsi1; ++ ethernet0 = &rp1_eth; ++ fb = &fb; ++ gpio0 = &gpio; ++ gpio1 = &gio; ++ gpio2 = &gio_aon; ++ gpio3 = &pinctrl; ++ gpio4 = &pinctrl_aon; ++ i2c = &i2c_arm; ++ i2c0 = &i2c0; ++ i2c1 = &i2c1; ++ i2c10 = &i2c_rp1boot; ++ i2c2 = &i2c2; ++ i2c3 = &i2c3; ++ i2c4 = &i2c4; ++ i2c5 = &i2c5; ++ i2c6 = &i2c6; ++ mailbox = &mailbox; ++ mmc0 = &sdio1; ++ serial0 = &uart0; ++ serial1 = &uart1; ++ serial10 = &uart10; ++ serial2 = &uart2; ++ serial3 = &uart3; ++ serial4 = &uart4; ++ spi0 = &spi0; ++ spi1 = &spi1; ++ spi10 = &spi10; ++ spi2 = &spi2; ++ spi3 = &spi3; ++ spi4 = &spi4; ++ spi5 = &spi5; ++ uart0 = &uart0; ++ uart1 = &uart1; ++ uart10 = &uart10; ++ uart2 = &uart2; ++ uart3 = &uart3; ++ uart4 = &uart4; ++ usb0 = &rp1_usb0; ++ usb1 = &rp1_usb1; ++ wifi0 = &wifi; ++ }; ++ + __overrides__ { +- arm_freq; ++ act_led_gpio = <&led_act>,"gpios:4",<&led_act>,"gpios:0=",<&gpio>; ++ act_led_activelow = <&led_act>, "gpios:8"; ++ act_led_trigger = <&led_act>, "linux,default-trigger"; + axiperf = <&axiperf>,"status"; +- ++ bdaddr = <&bluetooth>, "local-bd-address["; ++ button_debounce = <&pwr_key>, "debounce-interval:0"; ++ cooling_fan = <&fan>, "status", <&rp1_pwm1>, "status"; ++ drm_fb0_rp1_dpi = <&aliases>, "drm-fb0=",&dpi; ++ drm_fb0_rp1_dsi0 = <&aliases>, "drm-fb0=",&dsi0; ++ drm_fb0_rp1_dsi1 = <&aliases>, "drm-fb0=",&dsi1; ++ drm_fb0_vc4 = <&aliases>, "drm-fb0=",&vc4; ++ drm_fb1_rp1_dpi = <&aliases>, "drm-fb1=",&dpi; ++ drm_fb1_rp1_dsi0 = <&aliases>, "drm-fb1=",&dsi0; ++ drm_fb1_rp1_dsi1 = <&aliases>, "drm-fb1=",&dsi1; ++ drm_fb1_vc4 = <&aliases>, "drm-fb1=",&vc4; ++ drm_fb2_rp1_dpi = <&aliases>, "drm-fb2=",&dpi; ++ drm_fb2_rp1_dsi0 = <&aliases>, "drm-fb2=",&dsi0; ++ drm_fb2_rp1_dsi1 = <&aliases>, "drm-fb2=",&dsi1; ++ drm_fb2_vc4 = <&aliases>, "drm-fb2=",&vc4; ++ eth_led0 = <&phy1>,"led-modes:0"; ++ eth_led1 = <&phy1>,"led-modes:4"; ++ fan_temp0 = <&cpu_tepid>,"temperature:0"; ++ fan_temp0_hyst = <&cpu_tepid>,"hysteresis:0"; ++ fan_temp0_speed = <&fan>, "cooling-levels:4"; ++ fan_temp1 = <&cpu_warm>,"temperature:0"; ++ fan_temp1_hyst = <&cpu_warm>,"hysteresis:0"; ++ fan_temp1_speed = <&fan>, "cooling-levels:8"; ++ fan_temp2 = <&cpu_hot>,"temperature:0"; ++ fan_temp2_hyst = <&cpu_hot>,"hysteresis:0"; ++ fan_temp2_speed = <&fan>, "cooling-levels:12"; ++ fan_temp3 = <&cpu_vhot>,"temperature:0"; ++ fan_temp3_hyst = <&cpu_vhot>,"hysteresis:0"; ++ fan_temp3_speed = <&fan>, "cooling-levels:16"; ++ i2c = <&i2c1>, "status"; ++ i2c_arm = <&i2c_arm>, "status"; ++ i2c_arm_baudrate = <&i2c_arm>, "clock-frequency:0"; ++ i2c_baudrate = <&i2c_arm>, "clock-frequency:0"; ++ i2c_csi_dsi = <&i2c_csi_dsi>, "status"; ++ i2c_csi_dsi0 = <&i2c_csi_dsi0>, "status"; ++ i2c_csi_dsi1 = <&i2c_csi_dsi1>, "status"; ++ i2c_vc = <&i2c_vc>, "status"; ++ i2c_vc_baudrate = <&i2c_vc>, "clock-frequency:0"; ++ i2c0 = <&i2c0>, "status"; ++ i2c0_baudrate = <&i2c0>, "clock-frequency:0"; ++ i2c1 = <&i2c1>, "status"; ++ i2c1_baudrate = <&i2c1>, "clock-frequency:0"; ++ krnbt = <&bluetooth>, "status"; ++ nvme = <&pciex1>, "status"; + nvmem_cust_rw = <&nvmem_cust>,"rw?"; +- nvmem_priv_rw = <&nvmem_priv>,"rw?"; + nvmem_mac_rw = <&nvmem_mac>,"rw?"; ++ nvmem_priv_rw = <&nvmem_priv>,"rw?"; ++ pcie_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; ++ pciex1 = <&pciex1>, "status"; ++ pciex1_gen = <&pciex1> , "max-link-speed:0"; ++ pciex1_no_l0s = <&pciex1>, "aspm-no-l0s?"; ++ pciex1_tperst_clk_ms = <&pciex1>, "brcm,tperst-clk-ms:0"; ++ pwr_led_gpio = <&led_pwr>, "gpios:4"; ++ pwr_led_activelow = <&led_pwr>, "gpios:8"; ++ pwr_led_trigger = <&led_pwr>, "linux,default-trigger"; ++ random = <&random>, "status"; ++ rtc = <&rpi_rtc>, "status"; ++ rtc_bbat_vchg = <&rpi_rtc>, "trickle-charge-microvolt:0"; ++ spi = <&spi0>, "status"; + strict_gpiod = <&chosen>, "bootargs=pinctrl_rp1.persist_gpio_outputs=n"; ++ suspend = <&pwr_key>, "linux,code:0=205"; ++ uart0 = <&uart0>, "status"; ++ uart0_console = <&uart0>,"status", <&aliases>, "console=",&uart0; ++ wifiaddr = <&wifi>, "local-mac-address["; + + cam0_reg = <&cam0_reg>,"status"; + cam0_reg_gpio = <&cam0_reg>,"gpio:4", +@@ -113,7 +223,6 @@ + cam1_reg = <&cam1_reg>,"status"; + cam1_reg_gpio = <&cam1_reg>,"gpio:4", + <&cam1_reg>,"gpio:0=", <&gpio>; +- + }; + }; + diff --git a/target/linux/bcm27xx/patches-6.6/950-1183-arm64-dts-Give-cm5l-its-own-model-name.patch b/target/linux/bcm27xx/patches-6.6/950-1183-arm64-dts-Give-cm5l-its-own-model-name.patch new file mode 100644 index 0000000000..72279e130c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1183-arm64-dts-Give-cm5l-its-own-model-name.patch @@ -0,0 +1,24 @@ +From ad110e5ff36de6096e1b9d7e0fe125326f45ed7d Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 19 Jul 2024 13:18:47 +0100 +Subject: [PATCH 1183/1215] arm64: dts: Give cm5l its own model name + +The bootloader patches the DT with the correct model string, but it +is better not to rely on that by setting it from the start. + +Signed-off-by: Phil Elwell +--- + arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-cm5l.dtsi +@@ -4,6 +4,8 @@ + #include "bcm2712-rpi-cm5.dtsi" + + / { ++ model = "Raspberry Pi Compute Module 5 Lite"; ++ + __overrides__ { + i2c_csi_dsi = <&i2c_csi_dsi>, "status"; + }; diff --git a/target/linux/bcm27xx/patches-6.6/950-1185-pinctrl-rp1-jump-through-hoops-to-avoid-PCIe-latency.patch b/target/linux/bcm27xx/patches-6.6/950-1185-pinctrl-rp1-jump-through-hoops-to-avoid-PCIe-latency.patch new file mode 100644 index 0000000000..fecfb7a200 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1185-pinctrl-rp1-jump-through-hoops-to-avoid-PCIe-latency.patch @@ -0,0 +1,288 @@ +From d24229dcef58e0162780ceffa02eb5f6a01b9a4d Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Tue, 16 Jul 2024 16:47:08 +0100 +Subject: [PATCH 1185/1215] pinctrl: rp1: jump through hoops to avoid PCIe + latency issues + +Automatic link power saving plus the ability of a root complex to buffer +pending posted write transfers (and consider them complete before being +transmitted on the wire) causes compression of updates to GPIO state. + +The large bandwidth of a Gen 2 x4 link means the writes toggle state +inside RP1 as fast as it can go (~20MHz), which is bad for applications +wanting bitbash with at least a few microseconds of delay between +updates. + +By tailoring IO access patterns to a special Root Complex register, +writes to GPIOs can be stalled until the link wakes - meaning all writes +end up with a reasonably consistent minimum pacing (~200ns). + +Additionally, write barriers have no effect other than to arbitrarily +delay some writes by a small, variable amount - so remove the vast +majority of these in areas that could be hot-paths. + +Although the IO memory is mapped with Device strongly-ordered semantics, +this doesn't prevent the splitter inside BCM2712 from letting an MMIO +read request to a GPIO register get ahead of the pacing writes to the +Root Complex register. So each pin state read must flush writes out to +the Outer-Shareable domain. + +Signed-off-by: Jonathan Bell +--- + drivers/pinctrl/pinctrl-rp1.c | 120 +++++++++++++++++++++++++++++----- + 1 file changed, 105 insertions(+), 15 deletions(-) + +--- a/drivers/pinctrl/pinctrl-rp1.c ++++ b/drivers/pinctrl/pinctrl-rp1.c +@@ -197,6 +197,7 @@ struct rp1_pin_info { + void __iomem *inte; + void __iomem *ints; + void __iomem *pad; ++ void __iomem *dummy; + }; + + enum funcs { +@@ -276,6 +277,7 @@ struct rp1_pinctrl { + void __iomem *gpio_base; + void __iomem *rio_base; + void __iomem *pads_base; ++ void __iomem *dummy_base; + int irq[RP1_NUM_BANKS]; + struct rp1_pin_info pins[RP1_NUM_GPIOS]; + +@@ -577,6 +579,42 @@ static bool persist_gpio_outputs = true; + module_param(persist_gpio_outputs, bool, 0644); + MODULE_PARM_DESC(persist_gpio_outputs, "Enable GPIO_OUT persistence when pin is freed"); + ++static bool pace_pin_updates = true; ++module_param(pace_pin_updates, bool, 0644); ++MODULE_PARM_DESC(pace_pin_updates, "Update pin states with guaranteed monotonicity if PCIe ASPM is enabled"); ++ ++static inline void rp1_pin_writel(u32 val, void __iomem *dummy, void __iomem *reg) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ /* ++ * Issuing 6 pipelined writes to the RC's Slot Control register will stall the ++ * peripheral bus inside 2712 if the link is in L1. This acts as a lightweight ++ * "fence" operation preventing back-to-back writes arriving at RP1 on a wake. ++ */ ++ if (dummy) { ++ writel_relaxed(0, dummy); ++ writel_relaxed(0, dummy); ++ writel_relaxed(0, dummy); ++ writel_relaxed(0, dummy); ++ writel_relaxed(0, dummy); ++ writel_relaxed(0, dummy); ++ } ++ writel_relaxed(val, reg); ++ local_irq_restore(flags); ++} ++ ++static inline u32 rp1_pin_readl(const void __iomem *ioaddr) ++{ ++ /* ++ * Prior posted writes may not yet have been emitted by the CPU - do a store-flush ++ * before reading GPIO state, as this will serialise writes versus the next issued read. ++ */ ++ __dma_wmb(); ++ return readl(ioaddr); ++} ++ + static int rp1_pinconf_set(struct pinctrl_dev *pctldev, + unsigned int offset, unsigned long *configs, + unsigned int num_configs); +@@ -603,12 +641,12 @@ static struct rp1_pin_info *rp1_get_pin_ + + static void rp1_pad_update(struct rp1_pin_info *pin, u32 clr, u32 set) + { +- u32 padctrl = readl(pin->pad); ++ u32 padctrl = rp1_pin_readl(pin->pad); + + padctrl &= ~clr; + padctrl |= set; + +- writel(padctrl, pin->pad); ++ rp1_pin_writel(padctrl, pin->dummy, pin->pad); + } + + static void rp1_input_enable(struct rp1_pin_info *pin, int value) +@@ -625,7 +663,7 @@ static void rp1_output_enable(struct rp1 + + static u32 rp1_get_fsel(struct rp1_pin_info *pin) + { +- u32 ctrl = readl(pin->gpio + RP1_GPIO_CTRL); ++ u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL); + u32 oeover = FLD_GET(ctrl, RP1_GPIO_CTRL_OEOVER); + u32 fsel = FLD_GET(ctrl, RP1_GPIO_CTRL_FUNCSEL); + +@@ -637,7 +675,7 @@ static u32 rp1_get_fsel(struct rp1_pin_i + + static void rp1_set_fsel(struct rp1_pin_info *pin, u32 fsel) + { +- u32 ctrl = readl(pin->gpio + RP1_GPIO_CTRL); ++ u32 ctrl = rp1_pin_readl(pin->gpio + RP1_GPIO_CTRL); + + if (fsel >= RP1_FSEL_COUNT) + fsel = RP1_FSEL_NONE_HW; +@@ -652,12 +690,12 @@ static void rp1_set_fsel(struct rp1_pin_ + FLD_SET(ctrl, RP1_GPIO_CTRL_OEOVER, RP1_OEOVER_PERI); + } + FLD_SET(ctrl, RP1_GPIO_CTRL_FUNCSEL, fsel); +- writel(ctrl, pin->gpio + RP1_GPIO_CTRL); ++ rp1_pin_writel(ctrl, pin->dummy, pin->gpio + RP1_GPIO_CTRL); + } + + static int rp1_get_dir(struct rp1_pin_info *pin) + { +- return !(readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ? ++ return !(rp1_pin_readl(pin->rio + RP1_RIO_OE) & (1 << pin->offset)) ? + RP1_DIR_INPUT : RP1_DIR_OUTPUT; + } + +@@ -665,19 +703,19 @@ static void rp1_set_dir(struct rp1_pin_i + { + int offset = is_input ? RP1_CLR_OFFSET : RP1_SET_OFFSET; + +- writel(1 << pin->offset, pin->rio + RP1_RIO_OE + offset); ++ rp1_pin_writel(1 << pin->offset, pin->dummy, pin->rio + RP1_RIO_OE + offset); + } + + static int rp1_get_value(struct rp1_pin_info *pin) + { +- return !!(readl(pin->rio + RP1_RIO_IN) & (1 << pin->offset)); ++ return !!(rp1_pin_readl(pin->rio + RP1_RIO_IN) & (1 << pin->offset)); + } + + static void rp1_set_value(struct rp1_pin_info *pin, int value) + { + /* Assume the pin is already an output */ +- writel(1 << pin->offset, +- pin->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); ++ rp1_pin_writel(1 << pin->offset, pin->dummy, ++ pin->rio + RP1_RIO_OUT + (value ? RP1_SET_OFFSET : RP1_CLR_OFFSET)); + } + + static int rp1_gpio_get(struct gpio_chip *chip, unsigned offset) +@@ -1298,7 +1336,7 @@ static const struct pinmux_ops rp1_pmx_o + + static void rp1_pull_config_set(struct rp1_pin_info *pin, unsigned int arg) + { +- u32 padctrl = readl(pin->pad); ++ u32 padctrl = rp1_pin_readl(pin->pad); + + FLD_SET(padctrl, RP1_PAD_PULL, arg & 0x3); + +@@ -1398,7 +1436,7 @@ static int rp1_pinconf_get(struct pinctr + if (!pin) + return -EINVAL; + +- padctrl = readl(pin->pad); ++ padctrl = rp1_pin_readl(pin->pad); + + switch (param) { + case PIN_CONFIG_INPUT_ENABLE: +@@ -1493,6 +1531,7 @@ static int rp1_pinctrl_probe(struct plat + { + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; ++ struct device_node *rp1_node = NULL; + struct rp1_pinctrl *pc; + struct gpio_irq_chip *girq; + int err, i; +@@ -1528,6 +1567,40 @@ static int rp1_pinctrl_probe(struct plat + pc->gpio_chip = rp1_gpio_chip; + pc->gpio_chip.parent = dev; + ++ /* ++ * Workaround for the vagaries of PCIe on BCM2712 ++ * ++ * If the link to RP1 is in L1, then the BRCMSTB RC will buffer many ++ * outbound writes - and generate write responses for them, despite the ++ * fact that the link is not yet active. This has the effect of compressing ++ * multiple writes to GPIOs together, destroying any pacing that an application ++ * may require in the 1-10us range. ++ * ++ * The RC Slot Control configuration register is special. It emits a ++ * MsgD for every write to it, will stall further writes until the message ++ * goes out on the wire. This can be (ab)used to force CPU stalls when the ++ * link is inactive, at the cost of a small amount of downstream bandwidth ++ * and some 200ns of added latency for each write. ++ * ++ * Several back-to-back configuration writes are necessary to "fill the pipe", ++ * otherwise the outbound MAC can consume a pending MMIO write and reorder ++ * it with respect to the config writes - undoing the intent. ++ * ++ * of_iomap() is used directly here as the address overlaps with the RC driver's ++ * usage. ++ */ ++ rp1_node = of_find_node_by_name(NULL, "rp1"); ++ if (!rp1_node) ++ dev_err(&pdev->dev, "failed to find RP1 DT node\n"); ++ else if (pace_pin_updates && ++ of_device_is_compatible(rp1_node->parent, "brcm,bcm2712-pcie")) { ++ pc->dummy_base = of_iomap(rp1_node->parent, 0); ++ if (IS_ERR(pc->dummy_base)) { ++ dev_warn(&pdev->dev, "could not map bcm2712 root complex registers\n"); ++ pc->dummy_base = NULL; ++ } ++ } ++ + for (i = 0; i < RP1_NUM_BANKS; i++) { + const struct rp1_iobank_desc *bank = &rp1_iobanks[i]; + int j; +@@ -1547,14 +1620,17 @@ static int rp1_pinctrl_probe(struct plat + pin->rio = pc->rio_base + bank->rio_offset; + pin->pad = pc->pads_base + bank->pads_offset + + j * sizeof(u32); ++ pin->dummy = pc->dummy_base ? pc->dummy_base + 0xc0 : NULL; + } + + raw_spin_lock_init(&pc->irq_lock[i]); + } + + pc->pctl_dev = devm_pinctrl_register(dev, &rp1_pinctrl_desc, pc); +- if (IS_ERR(pc->pctl_dev)) +- return PTR_ERR(pc->pctl_dev); ++ if (IS_ERR(pc->pctl_dev)) { ++ err = PTR_ERR(pc->pctl_dev); ++ goto out_iounmap; ++ } + + girq = &pc->gpio_chip.irq; + girq->chip = &rp1_gpio_irq_chip; +@@ -1583,7 +1659,7 @@ static int rp1_pinctrl_probe(struct plat + err = devm_gpiochip_add_data(dev, &pc->gpio_chip, pc); + if (err) { + dev_err(dev, "could not add GPIO chip\n"); +- return err; ++ goto out_iounmap; + } + + pc->gpio_range = rp1_pinctrl_gpio_range; +@@ -1592,10 +1668,24 @@ static int rp1_pinctrl_probe(struct plat + pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); + + return 0; ++ ++out_iounmap: ++ if (pc->dummy_base) ++ iounmap(pc->dummy_base); ++ return err; ++} ++ ++static void rp1_pinctrl_remove(struct platform_device *pdev) ++{ ++ struct rp1_pinctrl *pc = platform_get_drvdata(pdev); ++ ++ if (pc->dummy_base) ++ iounmap(pc->dummy_base); + } + + static struct platform_driver rp1_pinctrl_driver = { + .probe = rp1_pinctrl_probe, ++ .remove_new = rp1_pinctrl_remove, + .driver = { + .name = MODULE_NAME, + .of_match_table = rp1_pinctrl_match, diff --git a/target/linux/bcm27xx/patches-6.6/950-1186-staging-bcm2835-codec-Disable-HEADER_ON_OPEN-for-vid.patch b/target/linux/bcm27xx/patches-6.6/950-1186-staging-bcm2835-codec-Disable-HEADER_ON_OPEN-for-vid.patch new file mode 100644 index 0000000000..a8fbeaf062 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1186-staging-bcm2835-codec-Disable-HEADER_ON_OPEN-for-vid.patch @@ -0,0 +1,36 @@ +From 43fa967811484afde0bbbee182ff8f29dc0550c2 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 5 Jul 2024 15:57:25 +0100 +Subject: [PATCH 1186/1215] staging: bcm2835-codec: Disable HEADER_ON_OPEN for + video encode + +Video encode can defer generating the header until the first +frame is presented, which allows it to take the colourspace +information from the frame rather than just the format. + +Enable that for the V4L2 driver now that the firmware populates +all the parameters. + +https://github.com/raspberrypi/firmware/issues/1885 + +Signed-off-by: Dave Stevenson +--- + .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c ++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +@@ -2731,6 +2731,13 @@ static int bcm2835_codec_create_componen + ¶ms, + sizeof(params)); + ++ } else if (dev->role == ENCODE) { ++ enable = 0; ++ vchiq_mmal_port_parameter_set(dev->instance, ++ &ctx->component->control, ++ MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN, ++ &enable, ++ sizeof(enable)); + } else if (dev->role == ENCODE_IMAGE) { + enable = 0; + vchiq_mmal_port_parameter_set(dev->instance, diff --git a/target/linux/bcm27xx/patches-6.6/950-1188-staging-bcm2835-codec-Add-support-for-H264-level-5.0.patch b/target/linux/bcm27xx/patches-6.6/950-1188-staging-bcm2835-codec-Add-support-for-H264-level-5.0.patch new file mode 100644 index 0000000000..f3c53adf50 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1188-staging-bcm2835-codec-Add-support-for-H264-level-5.0.patch @@ -0,0 +1,36 @@ +From 31b9871b8895d7931ee88d7cda7861f829b21d63 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Wed, 17 Jul 2024 16:59:08 +0100 +Subject: [PATCH 1188/1215] staging: bcm2835-codec: Add support for H264 level + 5.0 and 5.1 + +We do NOT claim to support decoding in real-time for these levels, +but can transcode some content, and handle 1920x1200. + +Signed-off-by: Dave Stevenson +--- + .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c ++++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +@@ -3273,7 +3273,7 @@ static void dec_add_profile_ctrls(struct + case V4L2_PIX_FMT_H264: + ctrl = v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_LEVEL, +- V4L2_MPEG_VIDEO_H264_LEVEL_4_2, ++ V4L2_MPEG_VIDEO_H264_LEVEL_5_1, + ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | +@@ -3287,7 +3287,9 @@ static void dec_add_profile_ctrls(struct + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0) | + BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_1) | +- BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2)), ++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_2) | ++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) | ++ BIT(V4L2_MPEG_VIDEO_H264_LEVEL_5_1)), + V4L2_MPEG_VIDEO_H264_LEVEL_4_0); + ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + ctrl = v4l2_ctrl_new_std_menu(hdl, &bcm2835_codec_ctrl_ops, diff --git a/target/linux/bcm27xx/patches-6.6/950-1189-spi-dw-Save-bandwidth-with-the-TMOD_TO-feature.patch b/target/linux/bcm27xx/patches-6.6/950-1189-spi-dw-Save-bandwidth-with-the-TMOD_TO-feature.patch new file mode 100644 index 0000000000..66ff22eb7f --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1189-spi-dw-Save-bandwidth-with-the-TMOD_TO-feature.patch @@ -0,0 +1,66 @@ +From 6014649de765a8a1f95c146ca72214ff0ba4ba89 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 1 Jul 2024 15:49:14 +0100 +Subject: [PATCH 1189/1215] spi: dw: Save bandwidth with the TMOD_TO feature + +TMOD_TO is the transmit-only mode that doesn't put data into the receive +FIFO. Using TMOD_TO when the user doesn't want the received data saves +CPU time and memory bandwidth. + +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-dw-core.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +--- a/drivers/spi/spi-dw-core.c ++++ b/drivers/spi/spi-dw-core.c +@@ -225,12 +225,17 @@ static irqreturn_t dw_spi_transfer_handl + * final stage of the transfer. By doing so we'll get the next IRQ + * right when the leftover incoming data is received. + */ +- dw_reader(dws); +- if (!dws->rx_len) { +- dw_spi_mask_intr(dws, 0xff); ++ if (dws->rx_len) { ++ dw_reader(dws); ++ if (!dws->rx_len) { ++ dw_spi_mask_intr(dws, 0xff); ++ spi_finalize_current_transfer(dws->host); ++ } else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) { ++ dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1); ++ } ++ } else if (!dws->tx_len) { ++ dw_spi_mask_intr(dws, DW_SPI_INT_TXEI); + spi_finalize_current_transfer(dws->host); +- } else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) { +- dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1); + } + + /* +@@ -239,12 +244,9 @@ static irqreturn_t dw_spi_transfer_handl + * have the TXE IRQ flood at the final stage of the transfer. + */ + if (irq_status & DW_SPI_INT_TXEI) { +- dw_writer(dws); +- if (!dws->tx_len) { ++ if (!dws->tx_len) + dw_spi_mask_intr(dws, DW_SPI_INT_TXEI); +- if (!dws->rx_len) +- spi_finalize_current_transfer(dws->host); +- } ++ dw_writer(dws); + } + + return IRQ_HANDLED; +@@ -437,6 +439,11 @@ static int dw_spi_transfer_one(struct sp + dws->rx = transfer->rx_buf; + dws->rx_len = dws->tx_len; + ++ if (!dws->rx) { ++ dws->rx_len = 0; ++ cfg.tmode = DW_SPI_CTRLR0_TMOD_TO; ++ } ++ + /* Ensure the data above is visible for all CPUs */ + smp_mb(); + diff --git a/target/linux/bcm27xx/patches-6.6/950-1190-spi-dw-Save-bandwidth-with-the-TMOD_RO-feature.patch b/target/linux/bcm27xx/patches-6.6/950-1190-spi-dw-Save-bandwidth-with-the-TMOD_RO-feature.patch new file mode 100644 index 0000000000..7791b99b6d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1190-spi-dw-Save-bandwidth-with-the-TMOD_RO-feature.patch @@ -0,0 +1,186 @@ +From cd9084ceb606a2f06c3429c2d3beae2d7c3ebd23 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 1 Jul 2024 16:41:04 +0100 +Subject: [PATCH 1190/1215] spi: dw: Save bandwidth with the TMOD_RO feature + +TMOD_RO is the receive-only mode that doesn't require data in the +transmit FIFO in order to generate clock cycles. Using TMOD_RO when the +device doesn't care about the data sent to it saves CPU time and memory +bandwidth. + +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-dw-core.c | 31 +++++++++++++++++++++------- + drivers/spi/spi-dw-dma.c | 43 +++++++++++++++++++++++++-------------- + 2 files changed, 52 insertions(+), 22 deletions(-) + +--- a/drivers/spi/spi-dw-core.c ++++ b/drivers/spi/spi-dw-core.c +@@ -367,18 +367,18 @@ static void dw_spi_irq_setup(struct dw_s + * will be adjusted at the final stage of the IRQ-based SPI transfer + * execution so not to lose the leftover of the incoming data. + */ +- level = min_t(unsigned int, dws->fifo_len / 2, dws->tx_len); ++ level = min_t(unsigned int, dws->fifo_len / 2, dws->tx_len ? dws->tx_len : dws->rx_len); + dw_writel(dws, DW_SPI_TXFTLR, level); + dw_writel(dws, DW_SPI_RXFTLR, level - 1); + + dws->transfer_handler = dw_spi_transfer_handler; + +- imask = 0; +- if (dws->tx_len) +- imask |= DW_SPI_INT_TXEI | DW_SPI_INT_TXOI; ++ imask = DW_SPI_INT_TXEI | DW_SPI_INT_TXOI; + if (dws->rx_len) + imask |= DW_SPI_INT_RXUI | DW_SPI_INT_RXOI | DW_SPI_INT_RXFI; + dw_spi_umask_intr(dws, imask); ++ if (!dws->tx_len) ++ dw_writel(dws, DW_SPI_DR, 0); + } + + /* +@@ -401,13 +401,18 @@ static int dw_spi_poll_transfer(struct d + delay.unit = SPI_DELAY_UNIT_SCK; + nbits = dws->n_bytes * BITS_PER_BYTE; + ++ if (!dws->tx_len) ++ dw_writel(dws, DW_SPI_DR, 0); ++ + do { +- dw_writer(dws); ++ if (dws->tx_len) ++ dw_writer(dws); + + delay.value = nbits * (dws->rx_len - dws->tx_len); + spi_delay_exec(&delay, transfer); + +- dw_reader(dws); ++ if (dws->rx_len) ++ dw_reader(dws); + + ret = dw_spi_check_status(dws, true); + if (ret) +@@ -427,6 +432,7 @@ static int dw_spi_transfer_one(struct sp + .dfs = transfer->bits_per_word, + .freq = transfer->speed_hz, + }; ++ int buswidth; + int ret; + + dws->dma_mapped = 0; +@@ -444,6 +450,18 @@ static int dw_spi_transfer_one(struct sp + cfg.tmode = DW_SPI_CTRLR0_TMOD_TO; + } + ++ if (!dws->rx) { ++ dws->rx_len = 0; ++ cfg.tmode = DW_SPI_CTRLR0_TMOD_TO; ++ } ++ if (!dws->tx) { ++ dws->tx_len = 0; ++ cfg.tmode = DW_SPI_CTRLR0_TMOD_RO; ++ cfg.ndf = dws->rx_len; ++ } ++ buswidth = transfer->rx_buf ? transfer->rx_nbits : ++ (transfer->tx_buf ? transfer->tx_nbits : 1); ++ + /* Ensure the data above is visible for all CPUs */ + smp_mb(); + +@@ -961,7 +979,6 @@ int dw_spi_add_host(struct device *dev, + dev_warn(dev, "DMA init failed\n"); + } else { + host->can_dma = dws->dma_ops->can_dma; +- host->flags |= SPI_CONTROLLER_MUST_TX; + } + } + +--- a/drivers/spi/spi-dw-dma.c ++++ b/drivers/spi/spi-dw-dma.c +@@ -6,6 +6,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -470,13 +471,12 @@ static int dw_spi_dma_setup(struct dw_sp + u16 imr, dma_ctrl; + int ret; + +- if (!xfer->tx_buf) +- return -EINVAL; +- + /* Setup DMA channels */ +- ret = dw_spi_dma_config_tx(dws); +- if (ret) +- return ret; ++ if (xfer->tx_buf) { ++ ret = dw_spi_dma_config_tx(dws); ++ if (ret) ++ return ret; ++ } + + if (xfer->rx_buf) { + ret = dw_spi_dma_config_rx(dws); +@@ -485,13 +485,17 @@ static int dw_spi_dma_setup(struct dw_sp + } + + /* Set the DMA handshaking interface */ +- dma_ctrl = DW_SPI_DMACR_TDMAE; ++ dma_ctrl = 0; ++ if (xfer->tx_buf) ++ dma_ctrl |= DW_SPI_DMACR_TDMAE; + if (xfer->rx_buf) + dma_ctrl |= DW_SPI_DMACR_RDMAE; + dw_writel(dws, DW_SPI_DMACR, dma_ctrl); + + /* Set the interrupt mask */ +- imr = DW_SPI_INT_TXOI; ++ imr = 0; ++ if (xfer->tx_buf) ++ imr |= DW_SPI_INT_TXOI; + if (xfer->rx_buf) + imr |= DW_SPI_INT_RXUI | DW_SPI_INT_RXOI; + dw_spi_umask_intr(dws, imr); +@@ -508,15 +512,16 @@ static int dw_spi_dma_transfer_all(struc + { + int ret; + +- /* Submit the DMA Tx transfer */ +- ret = dw_spi_dma_submit_tx(dws, xfer->tx_sg.sgl, xfer->tx_sg.nents); +- if (ret) +- goto err_clear_dmac; ++ /* Submit the DMA Tx transfer if required */ ++ if (xfer->tx_buf) { ++ ret = dw_spi_dma_submit_tx(dws, xfer->tx_sg.sgl, xfer->tx_sg.nents); ++ if (ret) ++ goto err_clear_dmac; ++ } + + /* Submit the DMA Rx transfer if required */ + if (xfer->rx_buf) { +- ret = dw_spi_dma_submit_rx(dws, xfer->rx_sg.sgl, +- xfer->rx_sg.nents); ++ ret = dw_spi_dma_submit_rx(dws, xfer->rx_sg.sgl, xfer->rx_sg.nents); + if (ret) + goto err_clear_dmac; + +@@ -524,7 +529,15 @@ static int dw_spi_dma_transfer_all(struc + dma_async_issue_pending(dws->rxchan); + } + +- dma_async_issue_pending(dws->txchan); ++ if (xfer->tx_buf) { ++ dma_async_issue_pending(dws->txchan); ++ } else { ++ /* Pause to allow DMA channel to fetch RX descriptor */ ++ usleep_range(5, 10); ++ ++ /* Write something to the TX FIFO to start the transfer */ ++ dw_writel(dws, DW_SPI_DR, 0); ++ } + + ret = dw_spi_dma_wait(dws, xfer->len, xfer->effective_speed_hz); + diff --git a/target/linux/bcm27xx/patches-6.6/950-1191-spi-dw-don-t-immediately-kill-DMA-transfers-if-an-er.patch b/target/linux/bcm27xx/patches-6.6/950-1191-spi-dw-don-t-immediately-kill-DMA-transfers-if-an-er.patch new file mode 100644 index 0000000000..45400204c4 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1191-spi-dw-don-t-immediately-kill-DMA-transfers-if-an-er.patch @@ -0,0 +1,41 @@ +From 3af7822df36e36b5a74d877df7654695c0e0d34a Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 22 Jul 2024 15:27:51 +0100 +Subject: [PATCH 1191/1215] spi: dw: don't immediately kill DMA transfers if an + error occurs + +Disabling the peripheral resets controller state which has a dangerous +side-effect of disabling the DMA handshake interface while it is active. +This can cause DMA channels to hang. + +The error recovery pathway will wait for DMA to stop and reset the chip +anyway, so mask further FIFO interrupts and let the transfer finish +gracefully. + +Signed-off-by: Jonathan Bell +--- + drivers/spi/spi-dw-core.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/spi/spi-dw-core.c ++++ b/drivers/spi/spi-dw-core.c +@@ -200,7 +200,18 @@ int dw_spi_check_status(struct dw_spi *d + + /* Generically handle the erroneous situation */ + if (ret) { +- dw_spi_reset_chip(dws); ++ /* ++ * Forcibly halting the controller can cause DMA to hang. ++ * Defer to dw_spi_handle_err outside of interrupt context ++ * and mask further interrupts for the current transfer. ++ */ ++ if (dws->dma_mapped) { ++ dw_spi_mask_intr(dws, 0xff); ++ dw_readl(dws, DW_SPI_ICR); ++ } else { ++ dw_spi_reset_chip(dws); ++ } ++ + if (dws->host->cur_msg) + dws->host->cur_msg->status = ret; + } diff --git a/target/linux/bcm27xx/patches-6.6/950-1192-dts-rp1-hobble-DMA-AXI-burst-lengths.patch b/target/linux/bcm27xx/patches-6.6/950-1192-dts-rp1-hobble-DMA-AXI-burst-lengths.patch new file mode 100644 index 0000000000..9cfdefec7d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1192-dts-rp1-hobble-DMA-AXI-burst-lengths.patch @@ -0,0 +1,35 @@ +From 4c1a665b465fa0e9d3369a467fc563ec812a47ce Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Fri, 19 Jul 2024 13:07:59 +0100 +Subject: [PATCH 1192/1215] dts: rp1: hobble DMA AXI burst lengths + +Channels 1-2 have a statically configured maximum MSIZE of 8, and +channels 3-8 have MSIZE set to 4. The DMAC "helpfully" silently +truncates bursts to the hardware supported maximum, so any FIFO read +operation with an oversized burst threshold will leave a residue of +threshold minus MSIZE rows. + +As channel allocation is dynamic, this means every client needs to use a +maximum of 4 for burst length. + +AXI AWLEN/ARLEN constraints aren't strictly related to MSIZE, except +that bursts won't be issued that are longer than MSIZE beats. Therefore, +it's a useful proxy to tell clients of the DMAC the hardware +limitations. + +Signed-off-by: Jonathan Bell +--- + arch/arm64/boot/dts/broadcom/rp1.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/broadcom/rp1.dtsi ++++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi +@@ -1064,7 +1064,7 @@ + snps,data-width = <4>; // (8 << 4) == 128 bits + snps,block-size = <0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000 0x40000>; + snps,priority = <0 1 2 3 4 5 6 7>; +- snps,axi-max-burst-len = <8>; ++ snps,axi-max-burst-len = <4>; + status = "disabled"; + }; + diff --git a/target/linux/bcm27xx/patches-6.6/950-1193-drivers-dw-axi-dmac-make-more-sensible-choices-about.patch b/target/linux/bcm27xx/patches-6.6/950-1193-drivers-dw-axi-dmac-make-more-sensible-choices-about.patch new file mode 100644 index 0000000000..d336532f46 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1193-drivers-dw-axi-dmac-make-more-sensible-choices-about.patch @@ -0,0 +1,124 @@ +From ce56098eb4dc2985f27f30ad7b7f5aed6bcf7fb1 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Fri, 19 Jul 2024 15:55:56 +0100 +Subject: [PATCH 1193/1215] drivers: dw-axi-dmac: make more sensible choices + about memory accesses + +There's no real need to constrain MEM access widths to 32-bit (or +narrower), as the DMAC is intelligent enough to size memory accesses +appropriately. Wider accesses are more efficient. + +Similarly, MEM burst lengths don't need to be a function of DEV burst +lengths - the DMAC packs/unpacks data into/from its internal channel +FIFOs appropriately. Longer accesses are more efficient. + +However, the DMAC doesn't have complete support for unaligned accesses, +and blocks are always defined in integer multiples of SRC_WIDTH, so odd +source lengths or buffer alignments will prevent wide accesses being +used, as before. + +There is an implicit requirement to limit requested DEV read burst +lengths to less than the hardware's maximum configured MSIZE - otherwise +RX data will be left over at the end of a block. There is no config +register that reports this value, so the AXI burst length parameter is +used to produce a facsimile of it. Warn if such a request arrives that +doesn't respect this. + +Signed-off-by: Jonathan Bell +--- + .../dma/dw-axi-dmac/dw-axi-dmac-platform.c | 38 ++++++++++++------- + 1 file changed, 25 insertions(+), 13 deletions(-) + +--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c ++++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +@@ -261,6 +261,15 @@ static u32 axi_chan_get_xfer_width(struc + return __ffs(src | dst | len | BIT(max_width)); + } + ++static u32 axi_dma_encode_msize(u32 max_burst) ++{ ++ if (max_burst <= 1) ++ return DWAXIDMAC_BURST_TRANS_LEN_1; ++ if (max_burst > 1024) ++ return DWAXIDMAC_BURST_TRANS_LEN_1024; ++ return fls(max_burst) - 2; ++} ++ + static inline const char *axi_chan_name(struct axi_dma_chan *chan) + { + return dma_chan_name(&chan->vc.chan); +@@ -685,41 +694,41 @@ static int dw_axi_dma_set_hw_desc(struct + size_t axi_block_ts; + size_t block_ts; + u32 ctllo, ctlhi; +- u32 burst_len; ++ u32 burst_len = 0, mem_burst_msize, reg_burst_msize; + + axi_block_ts = chan->chip->dw->hdata->block_size[chan->id]; + + mem_width = __ffs(data_width | mem_addr | len); +- if (mem_width > DWAXIDMAC_TRANS_WIDTH_32) +- mem_width = DWAXIDMAC_TRANS_WIDTH_32; + + if (!IS_ALIGNED(mem_addr, 4)) { + dev_err(chan->chip->dev, "invalid buffer alignment\n"); + return -EINVAL; + } + ++ /* Use a reasonable upper limit otherwise residue reporting granularity grows large */ ++ mem_burst_msize = axi_dma_encode_msize(16); ++ + switch (chan->direction) { + case DMA_MEM_TO_DEV: ++ reg_burst_msize = axi_dma_encode_msize(chan->config.dst_maxburst); + reg_width = __ffs(chan->config.dst_addr_width); + device_addr = phys_to_dma(chan->chip->dev, chan->config.dst_addr); + ctllo = reg_width << CH_CTL_L_DST_WIDTH_POS | + mem_width << CH_CTL_L_SRC_WIDTH_POS | +- DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_DST_MSIZE_POS | +- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS | ++ reg_burst_msize << CH_CTL_L_DST_MSIZE_POS | ++ mem_burst_msize << CH_CTL_L_SRC_MSIZE_POS | + DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS | + DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS; + block_ts = len >> mem_width; + break; + case DMA_DEV_TO_MEM: ++ reg_burst_msize = axi_dma_encode_msize(chan->config.src_maxburst); + reg_width = __ffs(chan->config.src_addr_width); +- /* Prevent partial access units getting lost */ +- if (mem_width > reg_width) +- mem_width = reg_width; + device_addr = phys_to_dma(chan->chip->dev, chan->config.src_addr); + ctllo = reg_width << CH_CTL_L_SRC_WIDTH_POS | + mem_width << CH_CTL_L_DST_WIDTH_POS | +- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | +- DWAXIDMAC_BURST_TRANS_LEN_1 << CH_CTL_L_SRC_MSIZE_POS | ++ mem_burst_msize << CH_CTL_L_DST_MSIZE_POS | ++ reg_burst_msize << CH_CTL_L_SRC_MSIZE_POS | + DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | + DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS; + block_ts = len >> reg_width; +@@ -760,6 +769,12 @@ static int dw_axi_dma_set_hw_desc(struct + set_desc_src_master(hw_desc); + + hw_desc->len = len; ++ ++ if (burst_len && (chan->config.src_maxburst > burst_len)) ++ dev_warn_ratelimited(chan2dev(chan), ++ "%s: requested source burst length %u exceeds supported burst length %u - data may be lost\n", ++ axi_chan_name(chan), chan->config.src_maxburst, burst_len); ++ + return 0; + } + +@@ -776,9 +791,6 @@ static size_t calculate_block_len(struct + case DMA_MEM_TO_DEV: + data_width = BIT(chan->chip->dw->hdata->m_data_width); + mem_width = __ffs(data_width | dma_addr | buf_len); +- if (mem_width > DWAXIDMAC_TRANS_WIDTH_32) +- mem_width = DWAXIDMAC_TRANS_WIDTH_32; +- + block_len = axi_block_ts << mem_width; + break; + case DMA_DEV_TO_MEM: diff --git a/target/linux/bcm27xx/patches-6.6/950-1195-tty-serial-pl011-restrict-RX-burst-FIFO-threshold.patch b/target/linux/bcm27xx/patches-6.6/950-1195-tty-serial-pl011-restrict-RX-burst-FIFO-threshold.patch new file mode 100644 index 0000000000..62731aeb34 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1195-tty-serial-pl011-restrict-RX-burst-FIFO-threshold.patch @@ -0,0 +1,30 @@ +From f3cb675102a2a5a330038c4e748f02b02cec989e Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 22 Jul 2024 09:30:54 +0100 +Subject: [PATCH 1195/1215] tty/serial: pl011: restrict RX burst FIFO threshold + +If the associated DMA controller has lower burst length support than the +level the FIFO is set to, then bytes will be left in the RX FIFO at the +end of a DMA block - requiring a round-trip through the timeout interrupt +handler rather than an end-of-block DMA interrupt. + +Signed-off-by: Jonathan Bell +--- + drivers/tty/serial/amba-pl011.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -487,6 +487,12 @@ static void pl011_dma_probe(struct uart_ + "RX DMA disabled - no residue processing\n"); + return; + } ++ /* ++ * DMA controllers with smaller burst capabilities than 1/4 ++ * the FIFO depth will leave more bytes than expected in the ++ * RX FIFO if mismatched. ++ */ ++ rx_conf.src_maxburst = min(caps.max_burst, rx_conf.src_maxburst); + } + dmaengine_slave_config(chan, &rx_conf); + uap->dmarx.chan = chan; diff --git a/target/linux/bcm27xx/patches-6.6/950-1196-DT-bindings-add-a-dma-maxburst-property-to-snps-desi.patch b/target/linux/bcm27xx/patches-6.6/950-1196-DT-bindings-add-a-dma-maxburst-property-to-snps-desi.patch new file mode 100644 index 0000000000..0d0afc2f9c --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1196-DT-bindings-add-a-dma-maxburst-property-to-snps-desi.patch @@ -0,0 +1,27 @@ +From 5112fd8cce4f1dc9bf43f0f90d35e273e1a0f555 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 22 Jul 2024 14:32:32 +0100 +Subject: [PATCH 1196/1215] DT: bindings: add a dma-maxburst property to + snps,designware-i2s + +Do an end-run around ASoC in lieu of not being able to easily find the +associated DMA controller capabilities. + +Signed-off-by: Jonathan Bell +--- + .../devicetree/bindings/sound/snps,designware-i2s.yaml | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml ++++ b/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml +@@ -69,6 +69,10 @@ properties: + - description: RX DMA Channel + minItems: 1 + ++ dma-maxburst: ++ description: FIFO DMA burst threshold limit ++ maxItems: 1 ++ + dma-names: + items: + - const: tx diff --git a/target/linux/bcm27xx/patches-6.6/950-1197-sound-soc-dwc-i2s-choose-FIFO-thresholds-based-on-DM.patch b/target/linux/bcm27xx/patches-6.6/950-1197-sound-soc-dwc-i2s-choose-FIFO-thresholds-based-on-DM.patch new file mode 100644 index 0000000000..d0e3bc1fab --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1197-sound-soc-dwc-i2s-choose-FIFO-thresholds-based-on-DM.patch @@ -0,0 +1,99 @@ +From b6b4260fa546d1dc7421c7cfed059052dae04227 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Thu, 18 Jul 2024 09:40:03 +0100 +Subject: [PATCH 1197/1215] sound/soc: dwc-i2s: choose FIFO thresholds based on + DMA burst constraints + +Valid ranges for the I2S peripheral's FIFO configuration include a depth +of 16 - unconditionally setting the burst length to 16 with a fifo +threshold of size/2 will cause under/overflows. + +For DMA engines with restricted capabilities the requested burst length +and FIFO thresholds need to be adjusted downward accordingly. + +Both the RX and TX FIFOs operate on "less-than" thresholds. Setting the +TX threshold to fifo_size minus burst means the FIFO is kept nearly-full. + +Signed-off-by: Jonathan Bell +--- + sound/soc/dwc/dwc-i2s.c | 21 ++++++++++++++++----- + sound/soc/dwc/local.h | 1 + + 2 files changed, 17 insertions(+), 5 deletions(-) + +--- a/sound/soc/dwc/dwc-i2s.c ++++ b/sound/soc/dwc/dwc-i2s.c +@@ -236,6 +236,8 @@ static void dw_i2s_config(struct dw_i2s_ + u32 ch_reg; + struct i2s_clk_config_data *config = &dev->config; + u32 dmacr; ++ u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1); ++ u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1)); + + i2s_disable_channels(dev, stream); + +@@ -251,7 +253,7 @@ static void dw_i2s_config(struct dw_i2s_ + i2s_write_reg(dev->i2s_base, TCR(ch_reg), + dev->xfer_resolution); + i2s_write_reg(dev->i2s_base, TFCR(ch_reg), +- dev->fifo_th - 1); ++ fifo_depth - dev->fifo_th - 1); + i2s_write_reg(dev->i2s_base, TER(ch_reg), TER_TXCHEN | + dev->tdm_mask << TER_TXSLOT_SHIFT); + dmacr |= (DMACR_DMAEN_TXCH0 << ch_reg); +@@ -783,8 +785,8 @@ static int dw_configure_dai_by_pd(struct + dev->capture_dma_data.pd.data = pdata->capture_dma_data; + dev->play_dma_data.pd.addr = res->start + I2S_TXDMA; + dev->capture_dma_data.pd.addr = res->start + I2S_RXDMA; +- dev->play_dma_data.pd.max_burst = 16; +- dev->capture_dma_data.pd.max_burst = 16; ++ dev->play_dma_data.pd.max_burst = dev->fifo_th; ++ dev->capture_dma_data.pd.max_burst = dev->fifo_th; + dev->play_dma_data.pd.addr_width = bus_widths[idx]; + dev->capture_dma_data.pd.addr_width = bus_widths[idx]; + dev->play_dma_data.pd.filter = pdata->filter; +@@ -815,7 +817,10 @@ static int dw_configure_dai_by_dt(struct + dev->play_dma_data.dt.addr = res->start + I2S_TXDMA; + dev->play_dma_data.dt.fifo_size = fifo_depth * + (fifo_width[idx2]) >> 8; +- dev->play_dma_data.dt.maxburst = 16; ++ if (dev->max_dma_burst) ++ dev->play_dma_data.dt.maxburst = dev->max_dma_burst; ++ else ++ dev->play_dma_data.dt.maxburst = fifo_depth / 2; + } + if (COMP1_RX_ENABLED(comp1)) { + idx2 = COMP2_RX_WORDSIZE_0(comp2); +@@ -824,9 +829,14 @@ static int dw_configure_dai_by_dt(struct + dev->capture_dma_data.dt.addr = res->start + I2S_RXDMA; + dev->capture_dma_data.dt.fifo_size = fifo_depth * + (fifo_width[idx2] >> 8); +- dev->capture_dma_data.dt.maxburst = 16; ++ if (dev->max_dma_burst) ++ dev->capture_dma_data.dt.maxburst = dev->max_dma_burst; ++ else ++ dev->capture_dma_data.dt.maxburst = fifo_depth / 2; + } + ++ if (dev->max_dma_burst) ++ dev->fifo_th = min(dev->max_dma_burst, dev->fifo_th); + return 0; + + } +@@ -1070,6 +1080,7 @@ static int dw_i2s_probe(struct platform_ + } + } + ++ of_property_read_u32(pdev->dev.of_node, "dma-maxburst", &dev->max_dma_burst); + dev->bclk_ratio = 0; + dev->i2s_reg_comp1 = I2S_COMP_PARAM_1; + dev->i2s_reg_comp2 = I2S_COMP_PARAM_2; +--- a/sound/soc/dwc/local.h ++++ b/sound/soc/dwc/local.h +@@ -133,6 +133,7 @@ struct dw_i2s_dev { + u32 ccr; + u32 xfer_resolution; + u32 fifo_th; ++ u32 max_dma_burst; + u32 l_reg; + u32 r_reg; + bool is_jh7110; /* Flag for StarFive JH7110 SoC */ diff --git a/target/linux/bcm27xx/patches-6.6/950-1198-dts-rp1-restrict-i2s-burst-lengths-to-4.patch b/target/linux/bcm27xx/patches-6.6/950-1198-dts-rp1-restrict-i2s-burst-lengths-to-4.patch new file mode 100644 index 0000000000..30b8a9f9b8 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1198-dts-rp1-restrict-i2s-burst-lengths-to-4.patch @@ -0,0 +1,30 @@ +From 062434ab3be76d4fa5973bb199ccfd5b68c11720 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Tue, 23 Jul 2024 11:21:47 +0100 +Subject: [PATCH 1198/1215] dts: rp1: restrict i2s burst lengths to 4 + +The associated DMAC has channels that do not support longer bursts. + +Signed-off-by: Jonathan Bell +--- + arch/arm64/boot/dts/broadcom/rp1.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm64/boot/dts/broadcom/rp1.dtsi ++++ b/arch/arm64/boot/dts/broadcom/rp1.dtsi +@@ -400,6 +400,7 @@ + #sound-dai-cells = <0>; + dmas = <&rp1_dma RP1_DMA_I2S0_TX>,<&rp1_dma RP1_DMA_I2S0_RX>; + dma-names = "tx", "rx"; ++ dma-maxburst = <4>; + status = "disabled"; + }; + +@@ -413,6 +414,7 @@ + #sound-dai-cells = <0>; + dmas = <&rp1_dma RP1_DMA_I2S1_TX>,<&rp1_dma RP1_DMA_I2S1_RX>; + dma-names = "tx", "rx"; ++ dma-maxburst = <4>; + status = "disabled"; + }; + diff --git a/target/linux/bcm27xx/patches-6.6/950-1199-drm-vc4-Disable-the-2pixel-clock-odd-timings-workaro.patch b/target/linux/bcm27xx/patches-6.6/950-1199-drm-vc4-Disable-the-2pixel-clock-odd-timings-workaro.patch new file mode 100644 index 0000000000..4c429e284d --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1199-drm-vc4-Disable-the-2pixel-clock-odd-timings-workaro.patch @@ -0,0 +1,204 @@ +From 485d11cfa7df2d2deb39c9b3455cebcb1a85cea2 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 25 Jul 2024 14:36:32 +0100 +Subject: [PATCH 1199/1215] drm/vc4: Disable the 2pixel/clock odd timings + workaround for interlaced + +Whilst BCM2712 does fix using odd horizontal timings, it doesn't +work with interlaced modes. + +Drop the workaround for interlaced modes and revert to the same +behaviour as BCM2711. + +https://github.com/raspberrypi/linux/issues/6281 + +Signed-off-by: Dave Stevenson +--- + drivers/gpu/drm/vc4/vc4_crtc.c | 20 +++++++++++++++++--- + drivers/gpu/drm/vc4/vc4_drv.h | 2 ++ + drivers/gpu/drm/vc4/vc4_hdmi.c | 8 +++++++- + drivers/gpu/drm/vc4/vc4_hdmi.h | 4 ++++ + 4 files changed, 30 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_crtc.c ++++ b/drivers/gpu/drm/vc4/vc4_crtc.c +@@ -378,7 +378,9 @@ static void vc4_crtc_config_pv(struct dr + bool is_dsi1 = vc4_encoder->type == VC4_ENCODER_TYPE_DSI1; + bool is_vec = vc4_encoder->type == VC4_ENCODER_TYPE_VEC; + u32 format = is_dsi1 ? PV_CONTROL_FORMAT_DSIV_24 : PV_CONTROL_FORMAT_24; +- u8 ppc = pv_data->pixels_per_clock; ++ u8 ppc = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? ++ pv_data->pixels_per_clock_int : ++ pv_data->pixels_per_clock; + + u16 vert_bp = mode->crtc_vtotal - mode->crtc_vsync_end; + u16 vert_sync = mode->crtc_vsync_end - mode->crtc_vsync_start; +@@ -443,7 +445,8 @@ static void vc4_crtc_config_pv(struct dr + */ + CRTC_WRITE(PV_V_CONTROL, + PV_VCONTROL_CONTINUOUS | +- (vc4->gen >= VC4_GEN_6 ? PV_VCONTROL_ODD_TIMING : 0) | ++ (vc4->gen >= VC4_GEN_6 && ppc == 1 ? ++ PV_VCONTROL_ODD_TIMING : 0) | + (is_dsi ? PV_VCONTROL_DSI : 0) | + PV_VCONTROL_INTERLACE | + (odd_field_first +@@ -455,7 +458,8 @@ static void vc4_crtc_config_pv(struct dr + } else { + CRTC_WRITE(PV_V_CONTROL, + PV_VCONTROL_CONTINUOUS | +- (vc4->gen >= VC4_GEN_6 ? PV_VCONTROL_ODD_TIMING : 0) | ++ (vc4->gen >= VC4_GEN_6 && ppc == 1 ? ++ PV_VCONTROL_ODD_TIMING : 0) | + (is_dsi ? PV_VCONTROL_DSI : 0)); + CRTC_WRITE(PV_VSYNCD_EVEN, 0); + } +@@ -1223,6 +1227,7 @@ const struct vc4_pv_data bcm2835_pv0_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 1, ++ .pixels_per_clock_int = 1, + .encoder_types = { + [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0, + [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI, +@@ -1238,6 +1243,7 @@ const struct vc4_pv_data bcm2835_pv1_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 1, ++ .pixels_per_clock_int = 1, + .encoder_types = { + [PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1, + [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI, +@@ -1253,6 +1259,7 @@ const struct vc4_pv_data bcm2835_pv2_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 1, ++ .pixels_per_clock_int = 1, + .encoder_types = { + [PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI0, + [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC, +@@ -1268,6 +1275,7 @@ const struct vc4_pv_data bcm2711_pv0_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 1, ++ .pixels_per_clock_int = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_DSI0, + [1] = VC4_ENCODER_TYPE_DPI, +@@ -1283,6 +1291,7 @@ const struct vc4_pv_data bcm2711_pv1_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 1, ++ .pixels_per_clock_int = 1, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_DSI1, + [1] = VC4_ENCODER_TYPE_SMI, +@@ -1298,6 +1307,7 @@ const struct vc4_pv_data bcm2711_pv2_dat + }, + .fifo_depth = 256, + .pixels_per_clock = 2, ++ .pixels_per_clock_int = 2, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI0, + }, +@@ -1312,6 +1322,7 @@ const struct vc4_pv_data bcm2711_pv3_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 1, ++ .pixels_per_clock_int = 1, + .encoder_types = { + [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC, + }, +@@ -1326,6 +1337,7 @@ const struct vc4_pv_data bcm2711_pv4_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 2, ++ .pixels_per_clock_int = 2, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI1, + }, +@@ -1339,6 +1351,7 @@ const struct vc4_pv_data bcm2712_pv0_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 1, ++ .pixels_per_clock_int = 2, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI0, + }, +@@ -1352,6 +1365,7 @@ const struct vc4_pv_data bcm2712_pv1_dat + }, + .fifo_depth = 64, + .pixels_per_clock = 1, ++ .pixels_per_clock_int = 2, + .encoder_types = { + [0] = VC4_ENCODER_TYPE_HDMI1, + }, +--- a/drivers/gpu/drm/vc4/vc4_drv.h ++++ b/drivers/gpu/drm/vc4/vc4_drv.h +@@ -569,6 +569,8 @@ struct vc4_pv_data { + + /* Number of pixels output per clock period */ + u8 pixels_per_clock; ++ /* Number of pixels output per clock period when in an interlaced mode */ ++ u8 pixels_per_clock_int; + + enum vc4_encoder_type encoder_types[4]; + }; +--- a/drivers/gpu/drm/vc4/vc4_hdmi.c ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c +@@ -2263,7 +2263,9 @@ static int vc4_hdmi_encoder_atomic_check + unsigned long long tmds_bit_rate; + int ret; + +- if (vc4_hdmi->variant->unsupported_odd_h_timings) { ++ if (vc4_hdmi->variant->unsupported_odd_h_timings || ++ (vc4_hdmi->variant->unsupported_int_odd_h_timings && ++ (mode->flags & DRM_MODE_FLAG_INTERLACE))) { + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { + /* Only try to fixup DBLCLK modes to get 480i and 576i + * working. +@@ -3974,6 +3976,7 @@ static const struct vc4_hdmi_variant bcm + PHY_LANE_CK, + }, + .unsupported_odd_h_timings = true, ++ .unsupported_int_odd_h_timings = true, + .external_irq_controller = true, + + .init_resources = vc5_hdmi_init_resources, +@@ -4003,6 +4006,7 @@ static const struct vc4_hdmi_variant bcm + PHY_LANE_2, + }, + .unsupported_odd_h_timings = true, ++ .unsupported_int_odd_h_timings = true, + .external_irq_controller = true, + + .init_resources = vc5_hdmi_init_resources, +@@ -4032,6 +4036,7 @@ static const struct vc4_hdmi_variant bcm + PHY_LANE_CK, + }, + .unsupported_odd_h_timings = false, ++ .unsupported_int_odd_h_timings = true, + .external_irq_controller = true, + + .init_resources = vc5_hdmi_init_resources, +@@ -4059,6 +4064,7 @@ static const struct vc4_hdmi_variant bcm + PHY_LANE_CK, + }, + .unsupported_odd_h_timings = false, ++ .unsupported_int_odd_h_timings = true, + .external_irq_controller = true, + + .init_resources = vc5_hdmi_init_resources, +--- a/drivers/gpu/drm/vc4/vc4_hdmi.h ++++ b/drivers/gpu/drm/vc4/vc4_hdmi.h +@@ -49,6 +49,10 @@ struct vc4_hdmi_variant { + + /* The BCM2711 cannot deal with odd horizontal pixel timings */ + bool unsupported_odd_h_timings; ++ /* The BCM2712 can handle odd horizontal pixel timings, but not in ++ * interlaced modes ++ */ ++ bool unsupported_int_odd_h_timings; + + /* + * The BCM2711 CEC/hotplug IRQ controller is shared between the diff --git a/target/linux/bcm27xx/patches-6.6/950-1200-ARM-dts-bcm2712-Fix-invalid-polling-delay-passive-se.patch b/target/linux/bcm27xx/patches-6.6/950-1200-ARM-dts-bcm2712-Fix-invalid-polling-delay-passive-se.patch new file mode 100644 index 0000000000..8a7d86d745 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1200-ARM-dts-bcm2712-Fix-invalid-polling-delay-passive-se.patch @@ -0,0 +1,26 @@ +From 70636ad110715b5e1ec6b08e24f0ddaf5df7186d Mon Sep 17 00:00:00 2001 +From: Dom Cobley +Date: Tue, 30 Jul 2024 19:00:03 +0100 +Subject: [PATCH 1200/1215] ARM: dts: bcm2712: Fix invalid + polling-delay-passive setting + +This produces a hard fail on later (6.11) kernels. + +See: https://lore.kernel.org/all/5802156.DvuYhMxLoT@rjwysocki.net/ + +Signed-off-by: Dom Cobley +--- + arch/arm64/boot/dts/broadcom/bcm2712.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi +@@ -40,7 +40,7 @@ + + thermal-zones { + cpu_thermal: cpu-thermal { +- polling-delay-passive = <2000>; ++ polling-delay-passive = <1000>; + polling-delay = <1000>; + coefficients = <(-550) 450000>; + thermal-sensors = <&thermal>; diff --git a/target/linux/bcm27xx/patches-6.6/950-1201-spi-dw-Fix-non-DMA-transmit-only-transfers.patch b/target/linux/bcm27xx/patches-6.6/950-1201-spi-dw-Fix-non-DMA-transmit-only-transfers.patch new file mode 100644 index 0000000000..6545c09186 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1201-spi-dw-Fix-non-DMA-transmit-only-transfers.patch @@ -0,0 +1,143 @@ +From 199e611183de09ad91fe01fc79da78cc9d11ccb6 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Mon, 29 Jul 2024 11:12:38 +0100 +Subject: [PATCH 1201/1215] spi: dw: Fix non-DMA transmit-only transfers + +Ensure the transmit FIFO has emptied before ending the transfer by +dropping the TX threshold to 0 when the last byte has been pushed into +the FIFO. Include a similar fix for the non-IRQ paths. + +See: https://github.com/raspberrypi/linux/issues/6285 +Fixes: 6014649de765 ("spi: dw: Save bandwidth with the TMOD_TO feature") +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-dw-core.c | 62 +++++++++++++++++++++++++++++++++------ + drivers/spi/spi-dw.h | 3 ++ + 2 files changed, 56 insertions(+), 9 deletions(-) + +--- a/drivers/spi/spi-dw-core.c ++++ b/drivers/spi/spi-dw-core.c +@@ -220,6 +220,32 @@ int dw_spi_check_status(struct dw_spi *d + } + EXPORT_SYMBOL_NS_GPL(dw_spi_check_status, SPI_DW_CORE); + ++static inline bool dw_spi_ctlr_busy(struct dw_spi *dws) ++{ ++ return dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_BUSY; ++} ++ ++static enum hrtimer_restart dw_spi_hrtimer_handler(struct hrtimer *hr) ++{ ++ struct dw_spi *dws = container_of(hr, struct dw_spi, hrtimer); ++ ++ if (!dw_spi_ctlr_busy(dws)) { ++ spi_finalize_current_transfer(dws->host); ++ return HRTIMER_NORESTART; ++ } ++ ++ if (!dws->idle_wait_retries) { ++ dev_err(&dws->host->dev, "controller stuck at busy\n"); ++ spi_finalize_current_transfer(dws->host); ++ return HRTIMER_NORESTART; ++ } ++ ++ dws->idle_wait_retries--; ++ hrtimer_forward_now(hr, dws->idle_wait_interval); ++ ++ return HRTIMER_RESTART; ++} ++ + static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws) + { + u16 irq_status = dw_readl(dws, DW_SPI_ISR); +@@ -246,7 +272,22 @@ static irqreturn_t dw_spi_transfer_handl + } + } else if (!dws->tx_len) { + dw_spi_mask_intr(dws, DW_SPI_INT_TXEI); +- spi_finalize_current_transfer(dws->host); ++ if (dw_spi_ctlr_busy(dws)) { ++ ktime_t period = ns_to_ktime(DIV_ROUND_UP(NSEC_PER_SEC, dws->current_freq)); ++ ++ /* ++ * Make the initial wait an underestimate of how long the transfer ++ * should take, then poll rapidly to reduce the delay ++ */ ++ hrtimer_start(&dws->hrtimer, ++ period * (8 * dws->n_bytes - 1), ++ HRTIMER_MODE_REL); ++ dws->idle_wait_retries = 10; ++ dws->idle_wait_interval = period; ++ } else { ++ spi_finalize_current_transfer(dws->host); ++ } ++ return IRQ_HANDLED; + } + + /* +@@ -255,9 +296,13 @@ static irqreturn_t dw_spi_transfer_handl + * have the TXE IRQ flood at the final stage of the transfer. + */ + if (irq_status & DW_SPI_INT_TXEI) { +- if (!dws->tx_len) +- dw_spi_mask_intr(dws, DW_SPI_INT_TXEI); + dw_writer(dws); ++ if (!dws->tx_len) { ++ if (dws->rx_len) ++ dw_spi_mask_intr(dws, DW_SPI_INT_TXEI); ++ else ++ dw_writel(dws, DW_SPI_TXFTLR, 0); ++ } + } + + return IRQ_HANDLED; +@@ -428,7 +473,7 @@ static int dw_spi_poll_transfer(struct d + ret = dw_spi_check_status(dws, true); + if (ret) + return ret; +- } while (dws->rx_len); ++ } while (dws->rx_len || dws->tx_len || dw_spi_ctlr_busy(dws)); + + return 0; + } +@@ -652,11 +697,6 @@ static int dw_spi_write_then_read(struct + return 0; + } + +-static inline bool dw_spi_ctlr_busy(struct dw_spi *dws) +-{ +- return dw_readl(dws, DW_SPI_SR) & DW_SPI_SR_BUSY; +-} +- + static int dw_spi_wait_mem_op_done(struct dw_spi *dws) + { + int retry = DW_SPI_WAIT_RETRIES; +@@ -993,6 +1033,9 @@ int dw_spi_add_host(struct device *dev, + } + } + ++ hrtimer_init(&dws->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); ++ dws->hrtimer.function = dw_spi_hrtimer_handler; ++ + ret = spi_register_controller(host); + if (ret) { + dev_err_probe(dev, ret, "problem registering spi host\n"); +@@ -1018,6 +1061,7 @@ void dw_spi_remove_host(struct dw_spi *d + { + dw_spi_debugfs_remove(dws); + ++ hrtimer_cancel(&dws->hrtimer); + spi_unregister_controller(dws->host); + + if (dws->dma_ops && dws->dma_ops->dma_exit) +--- a/drivers/spi/spi-dw.h ++++ b/drivers/spi/spi-dw.h +@@ -180,6 +180,9 @@ struct dw_spi { + u32 current_freq; /* frequency in hz */ + u32 cur_rx_sample_dly; + u32 def_rx_sample_dly_ns; ++ struct hrtimer hrtimer; ++ ktime_t idle_wait_interval; ++ int idle_wait_retries; + + /* Custom memory operations */ + struct spi_controller_mem_ops mem_ops; diff --git a/target/linux/bcm27xx/patches-6.6/950-1202-spi-dw-Clamp-the-minimum-clock-speed.patch b/target/linux/bcm27xx/patches-6.6/950-1202-spi-dw-Clamp-the-minimum-clock-speed.patch new file mode 100644 index 0000000000..585173aa44 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1202-spi-dw-Clamp-the-minimum-clock-speed.patch @@ -0,0 +1,26 @@ +From e9294823cf02068189a0e901223ed4991923c689 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 31 Jul 2024 10:55:19 +0100 +Subject: [PATCH 1202/1215] spi: dw: Clamp the minimum clock speed + +The DW SPI interface has a 16-bit clock divider, where the bottom bit +of the divisor must be 0. Limit how low the clock speed can go to +prevent the clock divider from being truncated, as that could lead to +a much higher clock rate than requested. + +Signed-off-by: Phil Elwell +--- + drivers/spi/spi-dw-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/spi/spi-dw-core.c ++++ b/drivers/spi/spi-dw-core.c +@@ -397,7 +397,7 @@ void dw_spi_update_config(struct dw_spi + dw_writel(dws, DW_SPI_CTRLR1, cfg->ndf ? cfg->ndf - 1 : 0); + + /* Note DW APB SSI clock divider doesn't support odd numbers */ +- clk_div = (DIV_ROUND_UP(dws->max_freq, cfg->freq) + 1) & 0xfffe; ++ clk_div = min(DIV_ROUND_UP(dws->max_freq, cfg->freq) + 1, 0xfffe) & 0xfffe; + speed_hz = dws->max_freq / clk_div; + + if (dws->current_freq != speed_hz) { diff --git a/target/linux/bcm27xx/patches-6.6/950-1203-overlays-i2c-rtc-Correct-bq32000-property-name.patch b/target/linux/bcm27xx/patches-6.6/950-1203-overlays-i2c-rtc-Correct-bq32000-property-name.patch new file mode 100644 index 0000000000..afd6c415ba --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1203-overlays-i2c-rtc-Correct-bq32000-property-name.patch @@ -0,0 +1,26 @@ +From 05e3687c6c973c30bf35f3b7f4a7589b5030a830 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 31 Jul 2024 13:19:26 +0100 +Subject: [PATCH 1203/1215] overlays: i2c-rtc: Correct bq32000 property name + +The DT property for the BQ32000 controlled by trickle-resistor-ohms +parameter should be "trickle-resistor-ohms", not "abracon,tc-resistor". + +See: https://github.com/raspberrypi/linux/issues/6291 + +Signed-off-by: Phil Elwell +--- + arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi ++++ b/arch/arm/boot/dts/overlays/i2c-rtc-common.dtsi +@@ -354,7 +354,7 @@ + <&rv3028>,"trickle-resistor-ohms:0", + <&rv3032>,"trickle-resistor-ohms:0", + <&rv1805>,"abracon,tc-resistor:0", +- <&bq32000>,"abracon,tc-resistor:0"; ++ <&bq32000>,"trickle-resistor-ohms:0"; + trickle-voltage-mv = <&rv3032>,"trickle-voltage-millivolts:0"; + backup-switchover-mode = <&rv3028>,"backup-switchover-mode:0"; + wakeup-source = <&ds1339>,"wakeup-source?", diff --git a/target/linux/bcm27xx/patches-6.6/950-1204-hwmon-adt7410-Add-DT-compatible-strings.patch b/target/linux/bcm27xx/patches-6.6/950-1204-hwmon-adt7410-Add-DT-compatible-strings.patch new file mode 100644 index 0000000000..cc54c62b91 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1204-hwmon-adt7410-Add-DT-compatible-strings.patch @@ -0,0 +1,31 @@ +From 16d0ee22d2c0b32cc67db73ce03263b740bba2a7 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Wed, 31 Jul 2024 15:02:47 +0100 +Subject: [PATCH 1204/1215] hwmon: (adt7410) Add DT compatible strings + +Signed-off-by: Phil Elwell +--- + drivers/hwmon/adt7410.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/hwmon/adt7410.c ++++ b/drivers/hwmon/adt7410.c +@@ -94,10 +94,18 @@ static const struct i2c_device_id adt741 + }; + MODULE_DEVICE_TABLE(i2c, adt7410_ids); + ++static const struct of_device_id adt7410_of_ids[] = { ++ { .compatible = "adi,adt7410" }, ++ { .compatible = "adi,adt7420" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, adt7410_of_ids); ++ + static struct i2c_driver adt7410_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adt7410", ++ .of_match_table = adt7410_of_ids, + .pm = pm_sleep_ptr(&adt7x10_dev_pm_ops), + }, + .probe = adt7410_i2c_probe, diff --git a/target/linux/bcm27xx/patches-6.6/950-1205-fixup-pinctrl-bcm2712-pinctrl-pinconf-driver.patch b/target/linux/bcm27xx/patches-6.6/950-1205-fixup-pinctrl-bcm2712-pinctrl-pinconf-driver.patch new file mode 100644 index 0000000000..fb786e172e --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1205-fixup-pinctrl-bcm2712-pinctrl-pinconf-driver.patch @@ -0,0 +1,23 @@ +From a4bf61fad9fe102514243ed263c458b053c87681 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Fri, 2 Aug 2024 11:29:03 +0100 +Subject: [PATCH 1205/1215] fixup! pinctrl: bcm2712 pinctrl/pinconf driver + +Fix cut-and-paste error spotted during upstreaming process. + +Signed-off-by: Phil Elwell +--- + drivers/pinctrl/bcm/pinctrl-bcm2712.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/pinctrl/bcm/pinctrl-bcm2712.c ++++ b/drivers/pinctrl/bcm/pinctrl-bcm2712.c +@@ -1029,7 +1029,7 @@ static int bcm2712_pinconf_get(struct pi + + *config = pinconf_to_config_packed(param, arg); + +- return -ENOTSUPP; ++ return 0; + } + + static int bcm2712_pinconf_set(struct pinctrl_dev *pctldev, diff --git a/target/linux/bcm27xx/patches-6.6/950-1206-dtoverlays-Add-overlay-for-HD44780-via-I2C-PCF8574-b.patch b/target/linux/bcm27xx/patches-6.6/950-1206-dtoverlays-Add-overlay-for-HD44780-via-I2C-PCF8574-b.patch new file mode 100644 index 0000000000..db5f472ff0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1206-dtoverlays-Add-overlay-for-HD44780-via-I2C-PCF8574-b.patch @@ -0,0 +1,125 @@ +From e94e761305fa2281718adcf625d78f3cf662e12d Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Thu, 1 Aug 2024 18:12:50 +0100 +Subject: [PATCH 1206/1215] dtoverlays: Add overlay for HD44780 via I2C PCF8574 + backpack + +Many HD44780 LCD displays are connected via very common I2C +GPIO expander. +We have an overlay for connecting the displays directly to GPIOs, +but not one for it connected via a backpack. Add such an overlay. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/Makefile | 1 + + arch/arm/boot/dts/overlays/README | 27 +++++++++ + .../dts/overlays/hd44780-i2c-lcd-overlay.dts | 57 +++++++++++++++++++ + 3 files changed, 85 insertions(+) + create mode 100644 arch/arm/boot/dts/overlays/hd44780-i2c-lcd-overlay.dts + +--- a/arch/arm/boot/dts/overlays/Makefile ++++ b/arch/arm/boot/dts/overlays/Makefile +@@ -82,6 +82,7 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ + gpio-no-irq.dtbo \ + gpio-poweroff.dtbo \ + gpio-shutdown.dtbo \ ++ hd44780-i2c-lcd.dtbo \ + hd44780-lcd.dtbo \ + hdmi-backlight-hwhack-gpio.dtbo \ + hifiberry-amp.dtbo \ +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1705,6 +1705,33 @@ Params: gpio_pin GPIO pin + (default 100) + + ++Name: hd44780-i2c-lcd ++Info: Configures an HD44780 compatible LCD display connected via a PCF8574 as ++ is often found as a backpack interface for these displays. ++Load: dtoverlay=hd44780-i2c-lcd,= ++Params: addr I2C address of PCF8574 ++ pin_d4 GPIO pin for data pin D4 (default 4) ++ ++ pin_d5 GPIO pin for data pin D5 (default 5) ++ ++ pin_d6 GPIO pin for data pin D6 (default 6) ++ ++ pin_d7 GPIO pin for data pin D7 (default 7) ++ ++ pin_en GPIO pin for "Enable" (default 2) ++ ++ pin_rs GPIO pin for "Register Select" (default 0) ++ ++ pin_rw GPIO pin for R/W select (default 1) ++ ++ pin_bl GPIO pin for enabling/disabling the display ++ backlight. (default 3) ++ ++ display_height Height of the display in characters (default 2) ++ ++ display_width Width of the display in characters (default 16) ++ ++ + Name: hd44780-lcd + Info: Configures an HD44780 compatible LCD display. Uses 4 gpio pins for + data, 2 gpio pins for enable and register select and 1 optional pin +--- /dev/null ++++ b/arch/arm/boot/dts/overlays/hd44780-i2c-lcd-overlay.dts +@@ -0,0 +1,57 @@ ++/dts-v1/; ++/plugin/; ++ ++/ { ++ compatible = "brcm,bcm2835"; ++ ++ fragment@0 { ++ target = <&i2c_arm>; ++ __overlay__ { ++ status = "okay"; ++ ++ pcf857x: pcf857x@27 { ++ compatible = "nxp,pcf8574"; ++ reg = <0x27>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ status = "okay"; ++ }; ++ }; ++ }; ++ ++ fragment@1 { ++ target-path = "/"; ++ __overlay__ { ++ lcd_screen: auxdisplay { ++ compatible = "hit,hd44780"; ++ ++ data-gpios = <&pcf857x 4 0>, ++ <&pcf857x 5 0>, ++ <&pcf857x 6 0>, ++ <&pcf857x 7 0>; ++ enable-gpios = <&pcf857x 2 0>; ++ rs-gpios = <&pcf857x 0 0>; ++ rw-gpios = <&pcf857x 1 0>; ++ backlight-gpios = <&pcf857x 3 0>; ++ ++ display-width-chars = <16>; ++ display-height-chars = <2>; ++ }; ++ }; ++ }; ++ ++ __overrides__ { ++ pin_d4 = <&lcd_screen>,"data-gpios:4"; ++ pin_d5 = <&lcd_screen>,"data-gpios:16"; ++ pin_d6 = <&lcd_screen>,"data-gpios:28"; ++ pin_d7 = <&lcd_screen>,"data-gpios:40"; ++ pin_en = <&lcd_screen>,"enable-gpios:4"; ++ pin_rs = <&lcd_screen>,"rs-gpios:4"; ++ pin_rw = <&lcd_screen>,"rw-gpios:4"; ++ pin_bl = <&lcd_screen>,"backlight-gpios:4"; ++ display_height = <&lcd_screen>,"display-height-chars:0"; ++ display_width = <&lcd_screen>,"display-width-chars:0"; ++ addr = <&pcf857x>,"reg:0"; ++ }; ++ ++}; diff --git a/target/linux/bcm27xx/patches-6.6/950-1207-dtoverlays-Document-display_-width-height-on-hd44780.patch b/target/linux/bcm27xx/patches-6.6/950-1207-dtoverlays-Document-display_-width-height-on-hd44780.patch new file mode 100644 index 0000000000..793cd49310 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1207-dtoverlays-Document-display_-width-height-on-hd44780.patch @@ -0,0 +1,28 @@ +From 3c319a466a1c718f66c471a9d5ec60de6de44612 Mon Sep 17 00:00:00 2001 +From: Dave Stevenson +Date: Fri, 2 Aug 2024 10:41:28 +0100 +Subject: [PATCH 1207/1215] dtoverlays: Document display_[width|height] on + hd44780-lcd overlay + +The default values defining a 16x2 display weren't documented, +so add them. + +Signed-off-by: Dave Stevenson +--- + arch/arm/boot/dts/overlays/README | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -1752,9 +1752,9 @@ Params: pin_d4 GPIO pin + pin_bl Optional pin for enabling/disabling the + display backlight. (default disabled) + +- display_height Height of the display in characters ++ display_height Height of the display in characters (default 2) + +- display_width Width of the display in characters ++ display_width Width of the display in characters (default 16) + + + Name: hdmi-backlight-hwhack-gpio diff --git a/target/linux/bcm27xx/patches-6.6/950-1208-DTS-bcm2712-enable-SD-slot-CQE-by-default-on-Pi-5.patch b/target/linux/bcm27xx/patches-6.6/950-1208-DTS-bcm2712-enable-SD-slot-CQE-by-default-on-Pi-5.patch new file mode 100644 index 0000000000..16e7603498 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1208-DTS-bcm2712-enable-SD-slot-CQE-by-default-on-Pi-5.patch @@ -0,0 +1,39 @@ +From 216df57950849f905c398904e7d6cbdf278b5717 Mon Sep 17 00:00:00 2001 +From: Jonathan Bell +Date: Mon, 5 Aug 2024 11:28:36 +0100 +Subject: [PATCH 1208/1215] DTS: bcm2712: enable SD slot CQE by default on Pi 5 + +The corresponding driver implementation has seen sufficient testing, +so enable by default. Retain the dtparam so it can be turned off for test. + +Signed-off-by: Jonathan Bell +--- + arch/arm/boot/dts/overlays/README | 6 +++--- + arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts | 1 + + 2 files changed, 4 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/overlays/README ++++ b/arch/arm/boot/dts/overlays/README +@@ -378,9 +378,9 @@ Params: + non-lite SKU of CM4). + (default "on") + +- sd_cqe Use to enable Command Queueing on the SD +- interface for faster Class A2 card performance +- (Pi 5 only, default "off") ++ sd_cqe Set to "off" to disable Command Queueing if you ++ have an incompatible Class A2 SD card ++ (Pi 5 only, default "on") + + sd_overclock Clock (in MHz) to use when the MMC framework + requests 50MHz +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi-5-b.dts +@@ -363,6 +363,7 @@ dpi_16bit_gpio2: &rp1_dpi_16bit_g + sd-uhs-sdr50; + sd-uhs-ddr50; + sd-uhs-sdr104; ++ supports-cqe; + cd-gpios = <&gio_aon 5 GPIO_ACTIVE_LOW>; + //no-1-8-v; + status = "okay"; diff --git a/target/linux/bcm27xx/patches-6.6/950-1211-gpiolib-Override-gpiochip-numbers-with-DT-aliases.patch b/target/linux/bcm27xx/patches-6.6/950-1211-gpiolib-Override-gpiochip-numbers-with-DT-aliases.patch new file mode 100644 index 0000000000..4ce9c04658 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1211-gpiolib-Override-gpiochip-numbers-with-DT-aliases.patch @@ -0,0 +1,50 @@ +From 53b9d9bbb57e292c6b332a2fb9899003586e17ca Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 May 2024 16:17:02 +0100 +Subject: [PATCH 1211/1215] gpiolib: Override gpiochip numbers with DT aliases + +In the same way that other subsystems support the setting of device +id numbers from Device Tree aliases, allow gpiochip numbers to be +derived from "gpiochip" aliases. + +Signed-off-by: Phil Elwell +--- + drivers/gpio/gpiolib.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -110,6 +110,7 @@ static int gpiochip_irqchip_init_valid_m + static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc); + + static bool gpiolib_initialized; ++static int first_dynamic_gpiochip_num = -1; + + static inline void desc_set_label(struct gpio_desc *d, const char *label) + { +@@ -745,6 +746,7 @@ int gpiochip_add_data_with_key(struct gp + unsigned int i; + int base = 0; + int ret = 0; ++ int id; + + /* + * First: allocate and populate the internal stat container, and +@@ -769,7 +771,16 @@ int gpiochip_add_data_with_key(struct gp + else if (gc->parent) + device_set_node(&gdev->dev, dev_fwnode(gc->parent)); + +- gdev->id = ida_alloc(&gpio_ida, GFP_KERNEL); ++ if (first_dynamic_gpiochip_num < 0) { ++ id = of_alias_get_highest_id("gpiochip"); ++ first_dynamic_gpiochip_num = (id >= 0) ? (id + 1) : 0; ++ } ++ ++ id = of_alias_get_id(gdev->dev.of_node, "gpiochip"); ++ if (id < 0) ++ id = first_dynamic_gpiochip_num; ++ ++ gdev->id = ida_alloc_range(&gpio_ida, id, ~0, GFP_KERNEL); + if (gdev->id < 0) { + ret = gdev->id; + goto err_free_gdev; diff --git a/target/linux/bcm27xx/patches-6.6/950-1212-dts-bcm2712-rpi-Add-gpiochip0-alias.patch b/target/linux/bcm27xx/patches-6.6/950-1212-dts-bcm2712-rpi-Add-gpiochip0-alias.patch new file mode 100644 index 0000000000..21913760a7 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1212-dts-bcm2712-rpi-Add-gpiochip0-alias.patch @@ -0,0 +1,23 @@ +From 1162316fd26eeb4193b23fcc1bb332f42938aa70 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 May 2024 16:58:59 +0100 +Subject: [PATCH 1212/1215] dts: bcm2712-rpi: Add gpiochip0 alias + +Add a gpiochip0 aliase pointing to the rp1 GPIO node, making it appear +as gpiochip0. + +Signed-off-by: Phil Elwell +--- + arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi +@@ -112,6 +112,7 @@ + gpio2 = &gio_aon; + gpio3 = &pinctrl; + gpio4 = &pinctrl_aon; ++ gpiochip0 = &gpio; + i2c = &i2c_arm; + i2c0 = &i2c0; + i2c1 = &i2c1; diff --git a/target/linux/bcm27xx/patches-6.6/950-1213-dts-bcm2712-rpi-The-SoC-gpiochips-start-at-10.patch b/target/linux/bcm27xx/patches-6.6/950-1213-dts-bcm2712-rpi-The-SoC-gpiochips-start-at-10.patch new file mode 100644 index 0000000000..5bf54c3fb0 --- /dev/null +++ b/target/linux/bcm27xx/patches-6.6/950-1213-dts-bcm2712-rpi-The-SoC-gpiochips-start-at-10.patch @@ -0,0 +1,24 @@ +From 70c640ce992234aacba5a717f3fb47319f451431 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Thu, 2 May 2024 17:40:25 +0100 +Subject: [PATCH 1213/1215] dts: bcm2712-rpi: The SoC gpiochips start at 10 + +Make the BCM2712's onboard GPIOs start at gpiochip10, marking them out +as system resources and preventing accidental use by existing Pi 5 +code. + +Signed-off-by: Phil Elwell +--- + arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi ++++ b/arch/arm64/boot/dts/broadcom/bcm2712-rpi.dtsi +@@ -113,6 +113,7 @@ + gpio3 = &pinctrl; + gpio4 = &pinctrl_aon; + gpiochip0 = &gpio; ++ gpiochip10 = &gio; + i2c = &i2c_arm; + i2c0 = &i2c0; + i2c1 = &i2c1; From ed4b434ab98773852d5a3ec54de8ef9adbedda9e Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 6 Aug 2024 10:42:27 +0200 Subject: [PATCH 07/12] mpc85xx: switch to kernel 6.6 It's time for wide tests. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/16087 Signed-off-by: Robert Marko --- target/linux/mpc85xx/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/linux/mpc85xx/Makefile b/target/linux/mpc85xx/Makefile index 7c8453776b..a095714c8a 100644 --- a/target/linux/mpc85xx/Makefile +++ b/target/linux/mpc85xx/Makefile @@ -11,8 +11,7 @@ CPU_TYPE:=8548 FEATURES:=squashfs ramdisk nand SUBTARGETS:=p1010 p1020 p2020 -KERNEL_PATCHVER:=6.1 -KERNEL_TESTING_PATCHVER:=6.6 +KERNEL_PATCHVER:=6.6 KERNELNAME:=zImage From eda9509bbaf51c7b5bb6dc438e800fe3556601f5 Mon Sep 17 00:00:00 2001 From: Pawel Dembicki Date: Tue, 6 Aug 2024 10:43:42 +0200 Subject: [PATCH 08/12] mpc85xx: remove 6.1 kernel support mpc85xx was switched to 6.6. We can remove 6.1 support now. Signed-off-by: Pawel Dembicki Link: https://github.com/openwrt/openwrt/pull/16087 Signed-off-by: Robert Marko --- target/linux/mpc85xx/config-6.1 | 295 ------------------ ...85xx-add-gpio-keys-to-of-match-table.patch | 10 - ...pc-add-compressed-zImage-for-mpc85xx.patch | 61 ---- ...0-powerpc-85xx-tl-wdr4900-v1-support.patch | 83 ----- .../101-powerpc-85xx-hiveap-330-support.patch | 58 ---- .../102-powerpc-add-cmdline-override.patch | 37 --- .../103-powerpc-85xx-red-15w-rev1.patch | 29 -- ...change-P2020RDB-dts-file-for-OpenWRT.patch | 170 ---------- .../105-powerpc-85xx-panda-support.patch | 30 -- .../106-powerpc-85xx-ws-ap3710i-support.patch | 60 ---- ...-powerpc-85xx-add-ws-ap3825i-support.patch | 67 ---- ...werpc-85xx-firebox-t10-support.patch.patch | 29 -- ...-powerpc-85xx-add-ws-ap3715i-support.patch | 48 --- .../110-powerpc-85xx-br200-wp-support.patch | 57 ---- .../111-powerpc-85xx-hpe-msm-support.patch | 31 -- ...pleboot-prevent-overwrite-of-CPU1-sp.patch | 41 --- ...ootwrapper-disable-uImage-generation.patch | 42 --- 17 files changed, 1148 deletions(-) delete mode 100644 target/linux/mpc85xx/config-6.1 delete mode 100644 target/linux/mpc85xx/patches-6.1/001-powerpc-85xx-add-gpio-keys-to-of-match-table.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/010-powerpc-add-compressed-zImage-for-mpc85xx.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/100-powerpc-85xx-tl-wdr4900-v1-support.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/101-powerpc-85xx-hiveap-330-support.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/102-powerpc-add-cmdline-override.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/103-powerpc-85xx-red-15w-rev1.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/104-powerpc-mpc85xx-change-P2020RDB-dts-file-for-OpenWRT.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/105-powerpc-85xx-panda-support.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/106-powerpc-85xx-ws-ap3710i-support.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/107-powerpc-85xx-add-ws-ap3825i-support.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/108-powerpc-85xx-firebox-t10-support.patch.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/109-powerpc-85xx-add-ws-ap3715i-support.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/110-powerpc-85xx-br200-wp-support.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/111-powerpc-85xx-hpe-msm-support.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/150-arch-powerpc-simpleboot-prevent-overwrite-of-CPU1-sp.patch delete mode 100644 target/linux/mpc85xx/patches-6.1/900-powerpc-bootwrapper-disable-uImage-generation.patch diff --git a/target/linux/mpc85xx/config-6.1 b/target/linux/mpc85xx/config-6.1 deleted file mode 100644 index c017422714..0000000000 --- a/target/linux/mpc85xx/config-6.1 +++ /dev/null @@ -1,295 +0,0 @@ -# CONFIG_40x is not set -# CONFIG_44x is not set -# CONFIG_ADVANCED_OPTIONS is not set -CONFIG_ARCH_32BIT_OFF_T=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_KEEP_MEMBLOCK=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y -CONFIG_ARCH_MMAP_RND_BITS=11 -CONFIG_ARCH_MMAP_RND_BITS_MAX=17 -CONFIG_ARCH_MMAP_RND_BITS_MIN=11 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 -CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y -CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y -CONFIG_ARCH_SPLIT_ARG64=y -CONFIG_ARCH_STACKWALK=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WEAK_RELEASE_ACQUIRE=y -CONFIG_ASN1=y -CONFIG_AUDIT_ARCH=y -CONFIG_BLK_MQ_PCI=y -CONFIG_BOOKE=y -CONFIG_BOOKE_OR_40x=y -CONFIG_BOOKE_WDT=y -# CONFIG_BR200_WP is not set -# CONFIG_BSC9131_RDB is not set -# CONFIG_BSC9132_QDS is not set -# CONFIG_C293_PCIE is not set -CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" -CONFIG_CC_NO_ARRAY_BOUNDS=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_CLZ_TAB=y -CONFIG_CMDLINE="console=ttyS0,115200" -CONFIG_CMDLINE_FROM_BOOTLOADER=y -# CONFIG_CMDLINE_OVERRIDE is not set -# CONFIG_COMMON_CLK is not set -CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 -CONFIG_COMPAT_32BIT_TIME=y -# CONFIG_CORENET_GENERIC is not set -# CONFIG_CPM2 is not set -CONFIG_CPU_BIG_ENDIAN=y -# CONFIG_CRYPTO_AES_PPC_SPE is not set -CONFIG_CRYPTO_AUTHENC=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y -CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 -CONFIG_CRYPTO_LIB_SHA1=y -CONFIG_CRYPTO_LIB_UTILS=y -# CONFIG_CRYPTO_MD5_PPC is not set -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RSA=y -# CONFIG_CRYPTO_SHA1_PPC is not set -# CONFIG_CRYPTO_SHA1_PPC_SPE is not set -# CONFIG_CRYPTO_SHA256_PPC_SPE is not set -CONFIG_DATA_SHIFT=24 -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -CONFIG_DNOTIFY=y -CONFIG_DTC=y -CONFIG_E500_CPU=y -CONFIG_EARLY_PRINTK=y -CONFIG_EDAC=y -CONFIG_EDAC_ATOMIC_SCRUB=y -# CONFIG_EDAC_DEBUG is not set -CONFIG_EDAC_LEGACY_SYSFS=y -CONFIG_EDAC_MPC85XX=y -CONFIG_EDAC_SUPPORT=y -CONFIG_EXCLUSIVE_SYSTEM_RAM=y -# CONFIG_FIREBOX_T10 is not set -CONFIG_FIXED_PHY=y -CONFIG_FSL_EMB_PERFMON=y -# CONFIG_FSL_FMAN is not set -CONFIG_FSL_LBC=y -CONFIG_FSL_PCI=y -CONFIG_FSL_PQ_MDIO=y -CONFIG_FSL_SOC=y -CONFIG_FSL_SOC_BOOKE=y -CONFIG_FWNODE_MDIO=y -CONFIG_FW_LOADER_PAGED_BUF=y -CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC11_NO_ARRAY_BOUNDS=y -CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_ATOMIC64=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_CPU_VULNERABILITIES=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_GETTIMEOFDAY=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GEN_RTC=y -# CONFIG_GE_IMP3A is not set -CONFIG_GIANFAR=y -CONFIG_GPIO_CDEV=y -CONFIG_GPIO_GENERIC=y -CONFIG_GPIO_MPC8XXX=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -# CONFIG_HIVEAP_330 is not set -CONFIG_HW_RANDOM=y -CONFIG_HZ_PERIODIC=y -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_MPC=y -CONFIG_ILLEGAL_POINTER_VALUE=0 -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -CONFIG_ISA_DMA_API=y -CONFIG_KERNEL_START=0xc0000000 -# CONFIG_KSI8560 is not set -CONFIG_LIBFDT=y -CONFIG_LOCK_DEBUGGING_SUPPORT=y -CONFIG_LOWMEM_CAM_NUM=9 -CONFIG_LOWMEM_SIZE=0x30000000 -CONFIG_LXT_PHY=y -# CONFIG_MATH_EMULATION is not set -CONFIG_MDIO_BUS=y -CONFIG_MDIO_DEVICE=y -CONFIG_MDIO_DEVRES=y -CONFIG_MEMFD_CREATE=y -CONFIG_MIGRATION=y -CONFIG_MMU_GATHER_MERGE_VMAS=y -CONFIG_MMU_GATHER_PAGE_SIZE=y -CONFIG_MODULES_USE_ELF_RELA=y -# CONFIG_MPC8536_DS is not set -# CONFIG_MPC8540_ADS is not set -# CONFIG_MPC8560_ADS is not set -# CONFIG_MPC85xx_CDS is not set -# CONFIG_MPC85xx_DS is not set -# CONFIG_MPC85xx_MDS is not set -# CONFIG_MPC85xx_RDB is not set -CONFIG_MPIC=y -# CONFIG_MPIC_MSGR is not set -CONFIG_MPIC_TIMER=y -CONFIG_MPILIB=y -# CONFIG_MSM460 is not set -# CONFIG_MTD_CFI is not set -CONFIG_MTD_NAND_CORE=y -CONFIG_MTD_NAND_ECC=y -CONFIG_MTD_NAND_ECC_SW_HAMMING=y -CONFIG_MTD_RAW_NAND=y -CONFIG_MTD_SPI_NOR=y -# CONFIG_MVME2500 is not set -CONFIG_NEED_PER_CPU_KM=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_NET_SELFTESTS=y -CONFIG_NLS=y -CONFIG_NR_CPUS=1 -CONFIG_NR_IRQS=512 -CONFIG_NVMEM=y -CONFIG_NVMEM_LAYOUTS=y -# CONFIG_NVMEM_QORIQ_EFUSE is not set -CONFIG_OF=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_DMA_DEFAULT_COHERENT=y -CONFIG_OF_EARLY_FLATTREE=y -CONFIG_OF_FLATTREE=y -CONFIG_OF_GPIO=y -CONFIG_OF_IRQ=y -CONFIG_OF_KOBJ=y -CONFIG_OF_MDIO=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND=y -# CONFIG_P1010_RDB is not set -# CONFIG_P1022_DS is not set -# CONFIG_P1022_RDK is not set -# CONFIG_P1023_RDB is not set -CONFIG_PAGE_OFFSET=0xc0000000 -CONFIG_PAGE_POOL=y -CONFIG_PAGE_SIZE_LESS_THAN_256KB=y -CONFIG_PAGE_SIZE_LESS_THAN_64KB=y -# CONFIG_PANDA is not set -CONFIG_PCI=y -CONFIG_PCIEAER=y -CONFIG_PCIEASPM=y -CONFIG_PCIEASPM_DEFAULT=y -# CONFIG_PCIEASPM_PERFORMANCE is not set -# CONFIG_PCIEASPM_POWERSAVE is not set -# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set -CONFIG_PCIEPORTBUS=y -CONFIG_PCI_DOMAINS=y -CONFIG_PGTABLE_LEVELS=2 -CONFIG_PHYLIB=y -CONFIG_PHYLIB_LEDS=y -CONFIG_PHYSICAL_ALIGN=0x04000000 -CONFIG_PHYSICAL_START=0x00000000 -# CONFIG_PHYS_64BIT is not set -# CONFIG_PMU_SYSFS is not set -# CONFIG_PPA8548 is not set -CONFIG_PPC=y -CONFIG_PPC32=y -# CONFIG_PPC64 is not set -CONFIG_PPC_85xx=y -# CONFIG_PPC_8xx is not set -CONFIG_PPC_ADV_DEBUG_DACS=2 -CONFIG_PPC_ADV_DEBUG_DVCS=0 -CONFIG_PPC_ADV_DEBUG_IACS=2 -CONFIG_PPC_ADV_DEBUG_REGS=y -CONFIG_PPC_BARRIER_NOSPEC=y -# CONFIG_PPC_BOOK3S_32 is not set -CONFIG_PPC_DOORBELL=y -CONFIG_PPC_E500=y -# CONFIG_PPC_E500MC is not set -# CONFIG_PPC_EARLY_DEBUG is not set -CONFIG_PPC_INDIRECT_PCI=y -CONFIG_PPC_KUAP=y -# CONFIG_PPC_KUAP_DEBUG is not set -CONFIG_PPC_KUEP=y -CONFIG_PPC_MMU_NOHASH=y -CONFIG_PPC_PAGE_SHIFT=12 -# CONFIG_PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT is not set -# CONFIG_PPC_QEMU_E500 is not set -CONFIG_PPC_SMP_MUXED_IPI=y -CONFIG_PPC_UDBG_16550=y -CONFIG_PPC_WERROR=y -CONFIG_PREEMPT_NONE_BUILD=y -CONFIG_PTP_1588_CLOCK_OPTIONAL=y -CONFIG_QE_GPIO=y -CONFIG_QUICC_ENGINE=y -CONFIG_RANDSTRUCT_NONE=y -CONFIG_RAS=y -# CONFIG_RED_15W_REV1 is not set -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_GENERIC=y -CONFIG_RTC_I2C_AND_SPI=y -CONFIG_RTC_MC146818_LIB=y -# CONFIG_SCOM_DEBUGFS is not set -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -CONFIG_SERIAL_MCTRL_GPIO=y -CONFIG_SERIAL_OF_PLATFORM=y -# CONFIG_SERIAL_QE is not set -# CONFIG_SOCRATES is not set -CONFIG_SOFTIRQ_ON_OWN_STACK=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPE=y -CONFIG_SPE_POSSIBLE=y -CONFIG_SPI=y -CONFIG_SPI_FSL_ESPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_MEM=y -CONFIG_SRCU=y -# CONFIG_STATIC_CALL_SELFTEST is not set -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_STX_GP3 is not set -CONFIG_SWPHY=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_TARGET_CPU="8540" -CONFIG_TARGET_CPU_BOOL=y -CONFIG_TASK_SIZE=0xc0000000 -CONFIG_THREAD_INFO_IN_TASK=y -CONFIG_THREAD_SHIFT=13 -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TINY_SRCU=y -# CONFIG_TL_WDR4900_V1 is not set -# CONFIG_TOOLCHAIN_DEFAULT_CPU is not set -# CONFIG_TQM8540 is not set -# CONFIG_TQM8541 is not set -# CONFIG_TQM8548 is not set -# CONFIG_TQM8555 is not set -# CONFIG_TQM8560 is not set -# CONFIG_TWR_P102x is not set -CONFIG_UCC=y -CONFIG_UCC_FAST=y -CONFIG_UCC_GETH=y -# CONFIG_UGETH_TX_ON_DEMAND is not set -CONFIG_USB_SUPPORT=y -CONFIG_VDSO32=y -# CONFIG_VIRT_CPU_ACCOUNTING_NATIVE is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_CORE=y -# CONFIG_WS_AP3710I is not set -# CONFIG_WS_AP3715I is not set -# CONFIG_WS_AP3825I is not set -# CONFIG_XES_MPC85xx is not set -CONFIG_XZ_DEC_BCJ=y -CONFIG_XZ_DEC_POWERPC=y diff --git a/target/linux/mpc85xx/patches-6.1/001-powerpc-85xx-add-gpio-keys-to-of-match-table.patch b/target/linux/mpc85xx/patches-6.1/001-powerpc-85xx-add-gpio-keys-to-of-match-table.patch deleted file mode 100644 index 5e5ab10daf..0000000000 --- a/target/linux/mpc85xx/patches-6.1/001-powerpc-85xx-add-gpio-keys-to-of-match-table.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/common.c -+++ b/arch/powerpc/platforms/85xx/common.c -@@ -30,6 +30,7 @@ static const struct of_device_id mpc85xx - { .compatible = "fsl,mpc8548-guts", }, - /* Probably unnecessary? */ - { .compatible = "gpio-leds", }, -+ { .compatible = "gpio-keys", }, - /* For all PCI controllers */ - { .compatible = "fsl,mpc8540-pci", }, - { .compatible = "fsl,mpc8548-pcie", }, diff --git a/target/linux/mpc85xx/patches-6.1/010-powerpc-add-compressed-zImage-for-mpc85xx.patch b/target/linux/mpc85xx/patches-6.1/010-powerpc-add-compressed-zImage-for-mpc85xx.patch deleted file mode 100644 index 16ef37bd78..0000000000 --- a/target/linux/mpc85xx/patches-6.1/010-powerpc-add-compressed-zImage-for-mpc85xx.patch +++ /dev/null @@ -1,61 +0,0 @@ -From b30ba76a980b3a9282f309c23e3bb0b0eb2c72cd Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Thu, 30 May 2024 02:55:38 +0200 -Subject: [PATCH] powerpc: add compressed zImage for mpc85xx - -Add a universal zImage which can be loaded by mpc85xx boards at -load address 0x3000000. This allows boards to boot kernels larger than -16MB even if the image is loaded temporarily from NAND at offset -0x1000000 which some bootloaders do by default. - -Signed-off-by: David Bauer ---- - arch/powerpc/boot/Makefile | 1 + - arch/powerpc/boot/wrapper | 5 +++++ - 2 files changed, 6 insertions(+) - ---- a/arch/powerpc/boot/Makefile -+++ b/arch/powerpc/boot/Makefile -@@ -175,6 +175,7 @@ src-plat-$(CONFIG_EMBEDDED6xx) += cuboot - src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c - src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c - src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c -+src-plat-$(CONFIG_PPC_ZIMAGE_LA3000000) += fixed-head.S - src-plat-$(CONFIG_PPC_PSERIES) += pseries-head.S - src-plat-$(CONFIG_PPC_POWERNV) += pseries-head.S - src-plat-$(CONFIG_PPC_IBM_CELL_BLADE) += pseries-head.S -@@ -345,6 +346,7 @@ image-$(CONFIG_MPC836x_MDS) += cuImage. - image-$(CONFIG_ASP834x) += dtbImage.asp834x-redboot - - # Board ports in arch/powerpc/platform/85xx/Kconfig -+image-$(CONFIG_PPC_ZIMAGE_LA3000000) += zImage.la3000000 - image-$(CONFIG_MPC8540_ADS) += cuImage.mpc8540ads - image-$(CONFIG_MPC8560_ADS) += cuImage.mpc8560ads - image-$(CONFIG_MPC85xx_CDS) += cuImage.mpc8541cds \ ---- a/arch/powerpc/boot/wrapper -+++ b/arch/powerpc/boot/wrapper -@@ -254,6 +254,11 @@ if [ -n "$esm_blob" -a "$platform" != "p - fi - - case "$platform" in -+la3000000) -+ binary=y -+ platformo="$object/fixed-head.o $object/of.o $object/epapr.o" -+ link_address='0x3000000' -+ ;; - of) - platformo="$object/of.o $object/epapr.o" - make_space=n ---- a/arch/powerpc/Kconfig -+++ b/arch/powerpc/Kconfig -@@ -74,6 +74,10 @@ config NMI_IPI - depends on SMP && (DEBUGGER || KEXEC_CORE || HARDLOCKUP_DETECTOR) - default y - -+config PPC_ZIMAGE_LA3000000 -+ bool -+ default n -+ - config PPC_WATCHDOG - bool - depends on HARDLOCKUP_DETECTOR diff --git a/target/linux/mpc85xx/patches-6.1/100-powerpc-85xx-tl-wdr4900-v1-support.patch b/target/linux/mpc85xx/patches-6.1/100-powerpc-85xx-tl-wdr4900-v1-support.patch deleted file mode 100644 index 5f8d84ccee..0000000000 --- a/target/linux/mpc85xx/patches-6.1/100-powerpc-85xx-tl-wdr4900-v1-support.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 1d9f596e572917772b87a2a37e1680902964782f Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -Date: Wed, 20 Feb 2013 08:40:33 +0100 -Subject: [PATCH] powerpc: 85xx: add support for the TP-Link TL-WDR4900 v1 - board - -This patch adds support for the TP-Link TL-WDR4900 v1 -concurrent dual-band wireless router. The devices uses -the Freescale P1014 SoC. - -Signed-off-by: Gabor Juhos -Signed-off-by: Pawel Dembicki ---- - arch/powerpc/boot/Makefile | 3 ++- - arch/powerpc/boot/wrapper | 5 +++++ - arch/powerpc/platforms/85xx/Kconfig | 12 ++++++++++++ - arch/powerpc/platforms/85xx/Makefile | 1 + - 4 files changed, 20 insertions(+), 1 deletion(-) - ---- a/arch/powerpc/boot/Makefile -+++ b/arch/powerpc/boot/Makefile -@@ -180,6 +180,7 @@ src-plat-$(CONFIG_PPC_PSERIES) += pserie - src-plat-$(CONFIG_PPC_POWERNV) += pseries-head.S - src-plat-$(CONFIG_PPC_IBM_CELL_BLADE) += pseries-head.S - src-plat-$(CONFIG_MVME7100) += motload-head.S mvme7100.c -+src-plat-$(CONFIG_TL_WDR4900_V1) += simpleboot.c fixed-head.S - - src-plat-$(CONFIG_PPC_MICROWATT) += fixed-head.S microwatt.c - -@@ -361,7 +362,7 @@ image-$(CONFIG_TQM8548) += cuImage.tqm - image-$(CONFIG_TQM8555) += cuImage.tqm8555 - image-$(CONFIG_TQM8560) += cuImage.tqm8560 - image-$(CONFIG_KSI8560) += cuImage.ksi8560 -- -+image-$(CONFIG_TL_WDR4900_V1) += simpleImage.tl-wdr4900-v1 - # Board ports in arch/powerpc/platform/86xx/Kconfig - image-$(CONFIG_MVME7100) += dtbImage.mvme7100 - ---- a/arch/powerpc/boot/wrapper -+++ b/arch/powerpc/boot/wrapper -@@ -346,6 +346,11 @@ adder875-redboot) - platformo="$object/fixed-head.o $object/redboot-8xx.o" - binary=y - ;; -+simpleboot-tl-wdr4900-v1) -+ platformo="$object/fixed-head.o $object/simpleboot.o" -+ link_address='0x1500000' -+ binary=y -+ ;; - simpleboot-*) - platformo="$object/fixed-head.o $object/simpleboot.o" - binary=y ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -163,6 +163,18 @@ config STX_GP3 - select CPM2 - select DEFAULT_UIMAGE - -+config TL_WDR4900_V1 -+ bool "TP-Link TL-WDR4900 v1" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ select SWIOTLB -+ help -+ This option enables support for the TP-Link TL-WDR4900 v1 board. -+ -+ This board is a Concurrent Dual-Band wireless router with a -+ Freescale P1014 SoC. -+ - config TQM8540 - bool "TQ Components TQM8540" - help ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_TWR_P102x) += twr_p102x.o - obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o - obj-$(CONFIG_FB_FSL_DIU) += t1042rdb_diu.o - obj-$(CONFIG_STX_GP3) += stx_gp3.o -+obj-$(CONFIG_TL_WDR4900_V1) += tl_wdr4900_v1.o - obj-$(CONFIG_TQM85xx) += tqm85xx.o - obj-$(CONFIG_PPA8548) += ppa8548.o - obj-$(CONFIG_SOCRATES) += socrates.o socrates_fpga_pic.o diff --git a/target/linux/mpc85xx/patches-6.1/101-powerpc-85xx-hiveap-330-support.patch b/target/linux/mpc85xx/patches-6.1/101-powerpc-85xx-hiveap-330-support.patch deleted file mode 100644 index 18466216c0..0000000000 --- a/target/linux/mpc85xx/patches-6.1/101-powerpc-85xx-hiveap-330-support.patch +++ /dev/null @@ -1,58 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -40,6 +40,17 @@ config BSC9132_QDS - and dual StarCore SC3850 DSP cores. - Manufacturer : Freescale Semiconductor, Inc - -+config HIVEAP_330 -+ bool "Aerohive HiveAP-330" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ help -+ This option enables support for the Aerohive HiveAP-330 board. -+ -+ This board is a Concurrent Dual-Band wireless access point with a -+ Freescale P1020 SoC. -+ - config MPC8540_ADS - bool "Freescale MPC8540 ADS" - select DEFAULT_UIMAGE ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -12,6 +12,7 @@ obj-y += common.o - obj-$(CONFIG_BSC9131_RDB) += bsc913x_rdb.o - obj-$(CONFIG_BSC9132_QDS) += bsc913x_qds.o - obj-$(CONFIG_C293_PCIE) += c293pcie.o -+obj-$(CONFIG_HIVEAP_330) += hiveap-330.o - obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o - obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o - obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o ---- a/arch/powerpc/boot/Makefile -+++ b/arch/powerpc/boot/Makefile -@@ -180,6 +180,7 @@ src-plat-$(CONFIG_PPC_PSERIES) += pserie - src-plat-$(CONFIG_PPC_POWERNV) += pseries-head.S - src-plat-$(CONFIG_PPC_IBM_CELL_BLADE) += pseries-head.S - src-plat-$(CONFIG_MVME7100) += motload-head.S mvme7100.c -+src-plat-$(CONFIG_HIVEAP_330) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_TL_WDR4900_V1) += simpleboot.c fixed-head.S - - src-plat-$(CONFIG_PPC_MICROWATT) += fixed-head.S microwatt.c -@@ -362,6 +363,7 @@ image-$(CONFIG_TQM8548) += cuImage.tqm - image-$(CONFIG_TQM8555) += cuImage.tqm8555 - image-$(CONFIG_TQM8560) += cuImage.tqm8560 - image-$(CONFIG_KSI8560) += cuImage.ksi8560 -+image-$(CONFIG_HIVEAP_330) += simpleImage.hiveap-330 - image-$(CONFIG_TL_WDR4900_V1) += simpleImage.tl-wdr4900-v1 - # Board ports in arch/powerpc/platform/86xx/Kconfig - image-$(CONFIG_MVME7100) += dtbImage.mvme7100 ---- a/arch/powerpc/boot/wrapper -+++ b/arch/powerpc/boot/wrapper -@@ -346,6 +346,7 @@ adder875-redboot) - platformo="$object/fixed-head.o $object/redboot-8xx.o" - binary=y - ;; -+simpleboot-hiveap-330|\ - simpleboot-tl-wdr4900-v1) - platformo="$object/fixed-head.o $object/simpleboot.o" - link_address='0x1500000' diff --git a/target/linux/mpc85xx/patches-6.1/102-powerpc-add-cmdline-override.patch b/target/linux/mpc85xx/patches-6.1/102-powerpc-add-cmdline-override.patch deleted file mode 100644 index 2ac10eae8e..0000000000 --- a/target/linux/mpc85xx/patches-6.1/102-powerpc-add-cmdline-override.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- a/arch/powerpc/Kconfig -+++ b/arch/powerpc/Kconfig -@@ -958,6 +958,14 @@ config CMDLINE_FORCE - - endchoice - -+config CMDLINE_OVERRIDE -+ bool "Use alternative cmdline from device tree" -+ help -+ Some bootloaders may have uneditable bootargs. While CMDLINE_FORCE can -+ be used, this is not a good option for kernels that are shared across -+ devices. This setting enables using "chosen/cmdline-override" as the -+ cmdline if it exists in the device tree. -+ - config EXTRA_TARGETS - string "Additional default image types" - help ---- a/drivers/of/fdt.c -+++ b/drivers/of/fdt.c -@@ -1187,6 +1187,17 @@ int __init early_init_dt_scan_chosen(cha - if (p != NULL && l > 0) - strlcat(cmdline, p, min_t(int, strlen(cmdline) + (int)l, COMMAND_LINE_SIZE)); - -+ /* CONFIG_CMDLINE_OVERRIDE is used to fallback to a different -+ * device tree option of chosen/bootargs-override. This is -+ * helpful on boards where u-boot sets bootargs, and is unable -+ * to be modified. -+ */ -+#ifdef CONFIG_CMDLINE_OVERRIDE -+ p = of_get_flat_dt_prop(node, "bootargs-override", &l); -+ if (p != NULL && l > 0) -+ strlcpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); -+#endif -+ - handle_cmdline: - /* - * CONFIG_CMDLINE is meant to be a default in case nothing else diff --git a/target/linux/mpc85xx/patches-6.1/103-powerpc-85xx-red-15w-rev1.patch b/target/linux/mpc85xx/patches-6.1/103-powerpc-85xx-red-15w-rev1.patch deleted file mode 100644 index 711d98abe7..0000000000 --- a/target/linux/mpc85xx/patches-6.1/103-powerpc-85xx-red-15w-rev1.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -166,6 +166,16 @@ config XES_MPC85xx - Manufacturer: Extreme Engineering Solutions, Inc. - URL: - -+config RED_15W_REV1 -+ bool "Sophos RED 15w Rev.1" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ help -+ This option enables support for the Sophos RED 15w Rev.1 board. -+ -+ This board is a wireless VPN router with a Freescale P1010 SoC. -+ - config STX_GP3 - bool "Silicon Turnkey Express GP3" - help ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_P1023_RDB) += p1023_rdb.o - obj-$(CONFIG_TWR_P102x) += twr_p102x.o - obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o - obj-$(CONFIG_FB_FSL_DIU) += t1042rdb_diu.o -+obj-$(CONFIG_RED_15W_REV1) += red15w_rev1.o - obj-$(CONFIG_STX_GP3) += stx_gp3.o - obj-$(CONFIG_TL_WDR4900_V1) += tl_wdr4900_v1.o - obj-$(CONFIG_TQM85xx) += tqm85xx.o diff --git a/target/linux/mpc85xx/patches-6.1/104-powerpc-mpc85xx-change-P2020RDB-dts-file-for-OpenWRT.patch b/target/linux/mpc85xx/patches-6.1/104-powerpc-mpc85xx-change-P2020RDB-dts-file-for-OpenWRT.patch deleted file mode 100644 index 94ed26c3df..0000000000 --- a/target/linux/mpc85xx/patches-6.1/104-powerpc-mpc85xx-change-P2020RDB-dts-file-for-OpenWRT.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 93514afd769c305182beeed1f9c4c46235879ef8 Mon Sep 17 00:00:00 2001 -From: Pawel Dembicki -Date: Sun, 30 Dec 2018 23:24:41 +0100 -Subject: [PATCH] powerpc: mpc85xx: change P2020RDB dts file for OpenWRT - -This patch apply chages for OpenWRT in P2020RDB -dts file. - -Signed-off-by: Pawel Dembicki ---- - arch/powerpc/boot/dts/fsl/p2020rdb.dts | 98 +++++++++++++++++--------- - 1 file changed, 63 insertions(+), 35 deletions(-) - ---- a/arch/powerpc/boot/dts/fsl/p2020rdb.dts -+++ b/arch/powerpc/boot/dts/fsl/p2020rdb.dts -@@ -5,10 +5,15 @@ - * Copyright 2009-2012 Freescale Semiconductor Inc. - */ - -+/dts-v1/; -+ - /include/ "p2020si-pre.dtsi" - -+#include -+#include -+ - / { -- model = "fsl,P2020RDB"; -+ model = "Freescale P2020RDB"; - compatible = "fsl,P2020RDB"; - - aliases { -@@ -34,48 +39,38 @@ - 0x2 0x0 0x0 0xffb00000 0x00020000>; - - nor@0,0 { -- #address-cells = <1>; -- #size-cells = <1>; - compatible = "cfi-flash"; - reg = <0x0 0x0 0x1000000>; - bank-width = <2>; - device-width = <1>; - -- partition@0 { -- /* This location must not be altered */ -- /* 256KB for Vitesse 7385 Switch firmware */ -- reg = <0x0 0x00040000>; -- label = "NOR (RO) Vitesse-7385 Firmware"; -- read-only; -- }; -- -- partition@40000 { -- /* 256KB for DTB Image */ -- reg = <0x00040000 0x00040000>; -- label = "NOR (RO) DTB Image"; -- read-only; -- }; -+ partitions { -+ compatible = "fixed-partitions"; -+ #address-cells = <1>; -+ #size-cells = <1>; - -- partition@80000 { -- /* 3.5 MB for Linux Kernel Image */ -- reg = <0x00080000 0x00380000>; -- label = "NOR (RO) Linux Kernel Image"; -- read-only; -- }; -+ partition@0 { -+ /* This location must not be altered */ -+ /* 256KB for Vitesse 7385 Switch firmware */ -+ reg = <0x0 0x00040000>; -+ label = "NOR (RO) Vitesse-7385 Firmware"; -+ read-only; -+ }; - -- partition@400000 { -- /* 11MB for JFFS2 based Root file System */ -- reg = <0x00400000 0x00b00000>; -- label = "NOR (RW) JFFS2 Root File System"; -- }; -+ partition@40000 { -+ compatible = "denx,fit"; -+ reg = <0x00040000 0x00ec0000>; -+ label = "firmware"; -+ }; - -- partition@f00000 { -- /* This location must not be altered */ -- /* 512KB for u-boot Bootloader Image */ -- /* 512KB for u-boot Environment Variables */ -- reg = <0x00f00000 0x00100000>; -- label = "NOR (RO) U-Boot Image"; -- read-only; -+ partition@f00000 { -+ /* This location must not be altered */ -+ /* 512KB for u-boot Bootloader Image */ -+ /* 512KB for u-boot Environment Variables */ -+ reg = <0x00f00000 0x00100000>; -+ label = "u-boot"; -+ read-only; -+ }; - }; - }; - -@@ -85,6 +80,7 @@ - compatible = "fsl,p2020-fcm-nand", - "fsl,elbc-fcm-nand"; - reg = <0x1 0x0 0x40000>; -+ nand-ecc-mode = "none"; - - partition@0 { - /* This location must not be altered */ -@@ -140,13 +136,43 @@ - soc: soc@ffe00000 { - ranges = <0x0 0x0 0xffe00000 0x100000>; - -+ gpio0: gpio-controller@fc00 { -+ }; -+ - i2c@3000 { -+ temperature-sensor@4c { -+ compatible = "adi,adt7461"; -+ reg = <0x4c>; -+ }; -+ -+ eeprom@50 { -+ compatible = "atmel,24c256"; -+ reg = <0x50>; -+ }; -+ - rtc@68 { - compatible = "dallas,ds1339"; - reg = <0x68>; - }; - }; - -+ i2c@3100 { -+ pmic@11 { -+ compatible = "zl2006"; -+ reg = <0x11>; -+ }; -+ -+ gpio@18 { -+ compatible = "nxp,pca9557"; -+ reg = <0x18>; -+ }; -+ -+ eeprom@52 { -+ compatible = "atmel,24c01"; -+ reg = <0x52>; -+ }; -+ }; -+ - spi@7000 { - flash@0 { - #address-cells = <1>; -@@ -200,10 +226,12 @@ - phy0: ethernet-phy@0 { - interrupts = <3 1 0 0>; - reg = <0x0>; -+ reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; - }; - phy1: ethernet-phy@1 { - interrupts = <3 1 0 0>; - reg = <0x1>; -+ reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; - }; - tbi-phy@2 { - device_type = "tbi-phy"; diff --git a/target/linux/mpc85xx/patches-6.1/105-powerpc-85xx-panda-support.patch b/target/linux/mpc85xx/patches-6.1/105-powerpc-85xx-panda-support.patch deleted file mode 100644 index 3c24a373ab..0000000000 --- a/target/linux/mpc85xx/patches-6.1/105-powerpc-85xx-panda-support.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -51,6 +51,17 @@ config HIVEAP_330 - This board is a Concurrent Dual-Band wireless access point with a - Freescale P1020 SoC. - -+config PANDA -+ bool "OCEDO PANDA" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ help -+ This option enables support for the OCEDO PANDA board. -+ -+ This board is a Concurrent Dual-Band wireless access point with a -+ Freescale P1020 SoC. -+ - config MPC8540_ADS - bool "Freescale MPC8540 ADS" - select DEFAULT_UIMAGE ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -24,6 +24,7 @@ obj-$(CONFIG_P1010_RDB) += p1010rdb.o - obj-$(CONFIG_P1022_DS) += p1022_ds.o - obj-$(CONFIG_P1022_RDK) += p1022_rdk.o - obj-$(CONFIG_P1023_RDB) += p1023_rdb.o -+obj-$(CONFIG_PANDA) += panda.o - obj-$(CONFIG_TWR_P102x) += twr_p102x.o - obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o - obj-$(CONFIG_FB_FSL_DIU) += t1042rdb_diu.o diff --git a/target/linux/mpc85xx/patches-6.1/106-powerpc-85xx-ws-ap3710i-support.patch b/target/linux/mpc85xx/patches-6.1/106-powerpc-85xx-ws-ap3710i-support.patch deleted file mode 100644 index 742fe7c2c0..0000000000 --- a/target/linux/mpc85xx/patches-6.1/106-powerpc-85xx-ws-ap3710i-support.patch +++ /dev/null @@ -1,60 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -62,6 +62,17 @@ config PANDA - This board is a Concurrent Dual-Band wireless access point with a - Freescale P1020 SoC. - -+config WS_AP3710I -+ bool "Enterasys WS-AP3710i" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ help -+ This option enables support for the Enterasys WS-AP3710i board. -+ -+ This board is a Concurrent Dual-Band wireless access point with a -+ Freescale P1020 SoC. -+ - config MPC8540_ADS - bool "Freescale MPC8540 ADS" - select DEFAULT_UIMAGE ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -26,6 +26,7 @@ obj-$(CONFIG_P1022_RDK) += p1022_rdk.o - obj-$(CONFIG_P1023_RDB) += p1023_rdb.o - obj-$(CONFIG_PANDA) += panda.o - obj-$(CONFIG_TWR_P102x) += twr_p102x.o -+obj-$(CONFIG_WS_AP3710I) += ws-ap3710i.o - obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o - obj-$(CONFIG_FB_FSL_DIU) += t1042rdb_diu.o - obj-$(CONFIG_RED_15W_REV1) += red15w_rev1.o ---- a/arch/powerpc/boot/Makefile -+++ b/arch/powerpc/boot/Makefile -@@ -182,6 +182,7 @@ src-plat-$(CONFIG_PPC_IBM_CELL_BLADE) += - src-plat-$(CONFIG_MVME7100) += motload-head.S mvme7100.c - src-plat-$(CONFIG_HIVEAP_330) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_TL_WDR4900_V1) += simpleboot.c fixed-head.S -+src-plat-$(CONFIG_WS_AP3710I) += simpleboot.c fixed-head.S - - src-plat-$(CONFIG_PPC_MICROWATT) += fixed-head.S microwatt.c - -@@ -365,6 +366,7 @@ image-$(CONFIG_TQM8560) += cuImage.tqm - image-$(CONFIG_KSI8560) += cuImage.ksi8560 - image-$(CONFIG_HIVEAP_330) += simpleImage.hiveap-330 - image-$(CONFIG_TL_WDR4900_V1) += simpleImage.tl-wdr4900-v1 -+image-$(CONFIG_WS_AP3710I) += simpleImage.ws-ap3710i - # Board ports in arch/powerpc/platform/86xx/Kconfig - image-$(CONFIG_MVME7100) += dtbImage.mvme7100 - ---- a/arch/powerpc/boot/wrapper -+++ b/arch/powerpc/boot/wrapper -@@ -347,7 +347,8 @@ adder875-redboot) - binary=y - ;; - simpleboot-hiveap-330|\ --simpleboot-tl-wdr4900-v1) -+simpleboot-tl-wdr4900-v1|\ -+simpleboot-ws-ap3710i) - platformo="$object/fixed-head.o $object/simpleboot.o" - link_address='0x1500000' - binary=y diff --git a/target/linux/mpc85xx/patches-6.1/107-powerpc-85xx-add-ws-ap3825i-support.patch b/target/linux/mpc85xx/patches-6.1/107-powerpc-85xx-add-ws-ap3825i-support.patch deleted file mode 100644 index 346001271b..0000000000 --- a/target/linux/mpc85xx/patches-6.1/107-powerpc-85xx-add-ws-ap3825i-support.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 2fa1a7983ef30f3c7486f9b07c001bee87d1f6d6 Mon Sep 17 00:00:00 2001 -From: Martin Kennedy -Date: Sat, 1 Jan 2022 11:01:37 -0500 -Subject: [PATCH] PowerPC 85xx: Add WS-AP3825i support - -This patch adds support for building Linux for the Extreme Networks -WS-AP3825i AP. - ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -73,6 +73,16 @@ config WS_AP3710I - This board is a Concurrent Dual-Band wireless access point with a - Freescale P1020 SoC. - -+config WS_AP3825I -+ bool "Extreme Networks WS-AP3825i" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ help -+ This option enables support for the Extreme Networks WS-AP3825i board. -+ This board is a Concurrent Dual-Band wireless access point with a -+ Freescale P1020 SoC. -+ - config MPC8540_ADS - bool "Freescale MPC8540 ADS" - select DEFAULT_UIMAGE ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_P1023_RDB) += p1023_rdb.o - obj-$(CONFIG_PANDA) += panda.o - obj-$(CONFIG_TWR_P102x) += twr_p102x.o - obj-$(CONFIG_WS_AP3710I) += ws-ap3710i.o -+obj-$(CONFIG_WS_AP3825I) += ws-ap3825i.o - obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o - obj-$(CONFIG_FB_FSL_DIU) += t1042rdb_diu.o - obj-$(CONFIG_RED_15W_REV1) += red15w_rev1.o ---- a/arch/powerpc/boot/Makefile -+++ b/arch/powerpc/boot/Makefile -@@ -183,6 +183,7 @@ src-plat-$(CONFIG_MVME7100) += motload-h - src-plat-$(CONFIG_HIVEAP_330) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_TL_WDR4900_V1) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_WS_AP3710I) += simpleboot.c fixed-head.S -+src-plat-$(CONFIG_WS_AP3825I) += simpleboot.c fixed-head.S - - src-plat-$(CONFIG_PPC_MICROWATT) += fixed-head.S microwatt.c - -@@ -367,6 +368,7 @@ image-$(CONFIG_KSI8560) += cuImage.ksi - image-$(CONFIG_HIVEAP_330) += simpleImage.hiveap-330 - image-$(CONFIG_TL_WDR4900_V1) += simpleImage.tl-wdr4900-v1 - image-$(CONFIG_WS_AP3710I) += simpleImage.ws-ap3710i -+image-$(CONFIG_WS_AP3825I) += simpleImage.ws-ap3825i - # Board ports in arch/powerpc/platform/86xx/Kconfig - image-$(CONFIG_MVME7100) += dtbImage.mvme7100 - ---- a/arch/powerpc/boot/wrapper -+++ b/arch/powerpc/boot/wrapper -@@ -348,7 +348,8 @@ adder875-redboot) - ;; - simpleboot-hiveap-330|\ - simpleboot-tl-wdr4900-v1|\ --simpleboot-ws-ap3710i) -+simpleboot-ws-ap3710i|\ -+simpleboot-ws-ap3825i) - platformo="$object/fixed-head.o $object/simpleboot.o" - link_address='0x1500000' - binary=y diff --git a/target/linux/mpc85xx/patches-6.1/108-powerpc-85xx-firebox-t10-support.patch.patch b/target/linux/mpc85xx/patches-6.1/108-powerpc-85xx-firebox-t10-support.patch.patch deleted file mode 100644 index 0b3a93b848..0000000000 --- a/target/linux/mpc85xx/patches-6.1/108-powerpc-85xx-firebox-t10-support.patch.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -83,6 +83,16 @@ config WS_AP3825I - This board is a Concurrent Dual-Band wireless access point with a - Freescale P1020 SoC. - -+config FIREBOX_T10 -+ bool "Watchguard Firebox T10" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ help -+ This option enables support for the Watchguard Firebox T10 board. -+ This board is a VPN Gateway-Router with a -+ Freescale P1010 SoC. -+ - config MPC8540_ADS - bool "Freescale MPC8540 ADS" - select DEFAULT_UIMAGE ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_PANDA) += panda.o - obj-$(CONFIG_TWR_P102x) += twr_p102x.o - obj-$(CONFIG_WS_AP3710I) += ws-ap3710i.o - obj-$(CONFIG_WS_AP3825I) += ws-ap3825i.o -+obj-$(CONFIG_FIREBOX_T10) += firebox_t10.o - obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o - obj-$(CONFIG_FB_FSL_DIU) += t1042rdb_diu.o - obj-$(CONFIG_RED_15W_REV1) += red15w_rev1.o diff --git a/target/linux/mpc85xx/patches-6.1/109-powerpc-85xx-add-ws-ap3715i-support.patch b/target/linux/mpc85xx/patches-6.1/109-powerpc-85xx-add-ws-ap3715i-support.patch deleted file mode 100644 index a9f7079866..0000000000 --- a/target/linux/mpc85xx/patches-6.1/109-powerpc-85xx-add-ws-ap3715i-support.patch +++ /dev/null @@ -1,48 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -73,6 +73,17 @@ config WS_AP3710I - This board is a Concurrent Dual-Band wireless access point with a - Freescale P1020 SoC. - -+config WS_AP3715I -+ bool "Enterasys WS-AP3715i" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ help -+ This option enables support for the Enterasys WS-AP3715i board. -+ -+ This board is a Concurrent Dual-Band wireless access point with a -+ Freescale P1010 SoC. -+ - config WS_AP3825I - bool "Extreme Networks WS-AP3825i" - select DEFAULT_UIMAGE ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_P1023_RDB) += p1023_rdb.o - obj-$(CONFIG_PANDA) += panda.o - obj-$(CONFIG_TWR_P102x) += twr_p102x.o - obj-$(CONFIG_WS_AP3710I) += ws-ap3710i.o -+obj-$(CONFIG_WS_AP3715I) += ws-ap3715i.o - obj-$(CONFIG_WS_AP3825I) += ws-ap3825i.o - obj-$(CONFIG_FIREBOX_T10) += firebox_t10.o - obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o ---- a/arch/powerpc/boot/Makefile -+++ b/arch/powerpc/boot/Makefile -@@ -183,6 +183,7 @@ src-plat-$(CONFIG_MVME7100) += motload-h - src-plat-$(CONFIG_HIVEAP_330) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_TL_WDR4900_V1) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_WS_AP3710I) += simpleboot.c fixed-head.S -+src-plat-$(CONFIG_WS_AP3715I) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_WS_AP3825I) += simpleboot.c fixed-head.S - - src-plat-$(CONFIG_PPC_MICROWATT) += fixed-head.S microwatt.c -@@ -368,6 +369,7 @@ image-$(CONFIG_KSI8560) += cuImage.ksi - image-$(CONFIG_HIVEAP_330) += simpleImage.hiveap-330 - image-$(CONFIG_TL_WDR4900_V1) += simpleImage.tl-wdr4900-v1 - image-$(CONFIG_WS_AP3710I) += simpleImage.ws-ap3710i -+image-$(CONFIG_WS_AP3715I) += simpleImage.ws-ap3715i - image-$(CONFIG_WS_AP3825I) += simpleImage.ws-ap3825i - # Board ports in arch/powerpc/platform/86xx/Kconfig - image-$(CONFIG_MVME7100) += dtbImage.mvme7100 diff --git a/target/linux/mpc85xx/patches-6.1/110-powerpc-85xx-br200-wp-support.patch b/target/linux/mpc85xx/patches-6.1/110-powerpc-85xx-br200-wp-support.patch deleted file mode 100644 index a58d12aef2..0000000000 --- a/target/linux/mpc85xx/patches-6.1/110-powerpc-85xx-br200-wp-support.patch +++ /dev/null @@ -1,57 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -40,6 +40,16 @@ config BSC9132_QDS - and dual StarCore SC3850 DSP cores. - Manufacturer : Freescale Semiconductor, Inc - -+config BR200_WP -+ bool "Aerohive BR200-WP" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ help -+ This option enables support for the Aerohive BR200-WP board. -+ -+ This board is a wireless router with a Freescale P1011 SoC. -+ - config HIVEAP_330 - bool "Aerohive HiveAP-330" - select DEFAULT_UIMAGE ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -12,6 +12,7 @@ obj-y += common.o - obj-$(CONFIG_BSC9131_RDB) += bsc913x_rdb.o - obj-$(CONFIG_BSC9132_QDS) += bsc913x_qds.o - obj-$(CONFIG_C293_PCIE) += c293pcie.o -+obj-$(CONFIG_BR200_WP) += br200-wp.o - obj-$(CONFIG_HIVEAP_330) += hiveap-330.o - obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o - obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o ---- a/arch/powerpc/boot/Makefile -+++ b/arch/powerpc/boot/Makefile -@@ -180,6 +180,7 @@ src-plat-$(CONFIG_PPC_PSERIES) += pserie - src-plat-$(CONFIG_PPC_POWERNV) += pseries-head.S - src-plat-$(CONFIG_PPC_IBM_CELL_BLADE) += pseries-head.S - src-plat-$(CONFIG_MVME7100) += motload-head.S mvme7100.c -+src-plat-$(CONFIG_BR200_WP) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_HIVEAP_330) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_TL_WDR4900_V1) += simpleboot.c fixed-head.S - src-plat-$(CONFIG_WS_AP3710I) += simpleboot.c fixed-head.S -@@ -366,6 +367,7 @@ image-$(CONFIG_TQM8548) += cuImage.tqm - image-$(CONFIG_TQM8555) += cuImage.tqm8555 - image-$(CONFIG_TQM8560) += cuImage.tqm8560 - image-$(CONFIG_KSI8560) += cuImage.ksi8560 -+image-$(CONFIG_BR200_WP) += simpleImage.br200-wp - image-$(CONFIG_HIVEAP_330) += simpleImage.hiveap-330 - image-$(CONFIG_TL_WDR4900_V1) += simpleImage.tl-wdr4900-v1 - image-$(CONFIG_WS_AP3710I) += simpleImage.ws-ap3710i ---- a/arch/powerpc/boot/wrapper -+++ b/arch/powerpc/boot/wrapper -@@ -346,6 +346,7 @@ adder875-redboot) - platformo="$object/fixed-head.o $object/redboot-8xx.o" - binary=y - ;; -+simpleboot-br200-wp|\ - simpleboot-hiveap-330|\ - simpleboot-tl-wdr4900-v1|\ - simpleboot-ws-ap3710i|\ diff --git a/target/linux/mpc85xx/patches-6.1/111-powerpc-85xx-hpe-msm-support.patch b/target/linux/mpc85xx/patches-6.1/111-powerpc-85xx-hpe-msm-support.patch deleted file mode 100644 index 4b9c6f8219..0000000000 --- a/target/linux/mpc85xx/patches-6.1/111-powerpc-85xx-hpe-msm-support.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/arch/powerpc/platforms/85xx/Kconfig -+++ b/arch/powerpc/platforms/85xx/Kconfig -@@ -114,6 +114,18 @@ config FIREBOX_T10 - This board is a VPN Gateway-Router with a - Freescale P1010 SoC. - -+config MSM460 -+ bool "HPE MSM460" -+ select DEFAULT_UIMAGE -+ select ARCH_REQUIRE_GPIOLIB -+ select GPIO_MPC8XXX -+ select PPC_ZIMAGE_LA3000000 -+ help -+ This option enables support for the HPE MSM460 board. -+ -+ This board is a Concurrent Dual-Band wireless access point with a -+ Freescale P1020 SoC. -+ - config MPC8540_ADS - bool "Freescale MPC8540 ADS" - select DEFAULT_UIMAGE ---- a/arch/powerpc/platforms/85xx/Makefile -+++ b/arch/powerpc/platforms/85xx/Makefile -@@ -21,6 +21,7 @@ obj-$(CONFIG_MPC8536_DS) += mpc8536_ds. - obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o - obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o - obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o -+obj-$(CONFIG_MSM460) += msm460.o - obj-$(CONFIG_P1010_RDB) += p1010rdb.o - obj-$(CONFIG_P1022_DS) += p1022_ds.o - obj-$(CONFIG_P1022_RDK) += p1022_rdk.o diff --git a/target/linux/mpc85xx/patches-6.1/150-arch-powerpc-simpleboot-prevent-overwrite-of-CPU1-sp.patch b/target/linux/mpc85xx/patches-6.1/150-arch-powerpc-simpleboot-prevent-overwrite-of-CPU1-sp.patch deleted file mode 100644 index 1ff80a5016..0000000000 --- a/target/linux/mpc85xx/patches-6.1/150-arch-powerpc-simpleboot-prevent-overwrite-of-CPU1-sp.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 5f856ccc34df25060d36a5a81b7b45b574d86e35 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Sun, 3 Dec 2023 20:09:24 +0100 -Subject: [PATCH] arch: powerpc: simpleboot: prevent overwrite of CPU1 - spin-table - -Don't overwrite the spin-table of additional CPU cores with loader-heap. - -U-Boot places the spin-table for CPU1 on P1020 SoCs in the top 1MB of -system-memory. Instead of parsing reserved-memory (which would be -considerable more work), reduce the available system-memory for the -loader by 1MB. - -This prevents the loader from overwriting the spin-table of -additional CPU cores on these platforms. - -Linux itself needs to be made aware by this using reserved-memory -definitions. - -This patch is required for using CPU1 on the Extreme Networks -WS-AP3825i. - -Signed-off-by: David Bauer ---- - arch/powerpc/boot/simpleboot.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/arch/powerpc/boot/simpleboot.c -+++ b/arch/powerpc/boot/simpleboot.c -@@ -65,6 +65,11 @@ void platform_init(unsigned long r3, uns - if (sizeof(void *) == 4 && memsize64 >= 0x100000000ULL) - memsize64 = 0xffffffff; - -+ /* Reserve upper 1 MB of memory for CPU1 spin-table */ -+ if (memsize64 > 0x100000) { -+ memsize64 = memsize64 - 0x100000; -+ } -+ - /* finally, setup the timebase */ - node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type", - "cpu", sizeof("cpu")); diff --git a/target/linux/mpc85xx/patches-6.1/900-powerpc-bootwrapper-disable-uImage-generation.patch b/target/linux/mpc85xx/patches-6.1/900-powerpc-bootwrapper-disable-uImage-generation.patch deleted file mode 100644 index a997a1b9b7..0000000000 --- a/target/linux/mpc85xx/patches-6.1/900-powerpc-bootwrapper-disable-uImage-generation.patch +++ /dev/null @@ -1,42 +0,0 @@ -From d43ab14605510d9d2bd257a8cd70f24ada4621b0 Mon Sep 17 00:00:00 2001 -From: David Bauer -Date: Sat, 29 Feb 2020 14:27:04 +0100 -Subject: [PATCH] powerpc: bootwrapper: disable uImage generation - -Due to CONFIG_KERNEL_XZ symbol, the bootwrapper code tries to -instruct the mkimage to use the xz compression, which isn't -supported. This disables the uImage generation, as OpenWrt -generates individual uImages for each board using it's own -toolchain. - -Signed-off-by: David Bauer ---- - arch/powerpc/boot/Makefile | 9 --------- - 1 file changed, 9 deletions(-) - ---- a/arch/powerpc/boot/Makefile -+++ b/arch/powerpc/boot/Makefile -@@ -294,7 +294,6 @@ image-$(CONFIG_PPC_CHRP) += zImage.chrp - image-$(CONFIG_PPC_EFIKA) += zImage.chrp - image-$(CONFIG_PPC_PMAC) += zImage.pmac - image-$(CONFIG_PPC_HOLLY) += dtbImage.holly --image-$(CONFIG_DEFAULT_UIMAGE) += uImage - image-$(CONFIG_EPAPR_BOOT) += zImage.epapr - - # -@@ -432,15 +431,6 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits - $(obj)/vmlinux.strip: vmlinux - $(STRIP) -s -R .comment $< -o $@ - --$(obj)/uImage: vmlinux $(wrapperbits) FORCE -- $(call if_changed,wrap,uboot) -- --$(obj)/uImage.initrd.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE -- $(call if_changed,wrap,uboot-$*,,$(obj)/dts/$*.dtb,$(obj)/ramdisk.image.gz) -- --$(obj)/uImage.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE -- $(call if_changed,wrap,uboot-$*,,$(obj)/dts/$*.dtb) -- - $(obj)/cuImage.initrd.%: vmlinux $(obj)/dts/%.dtb $(wrapperbits) FORCE - $(call if_changed,wrap,cuboot-$*,,$(obj)/dts/$*.dtb,$(obj)/ramdisk.image.gz) - From 2aa760acd688a22fa6a7c3c6a153ddd1099e92e4 Mon Sep 17 00:00:00 2001 From: Enrico Mioso Date: Tue, 2 Jul 2024 18:09:07 +0200 Subject: [PATCH 09/12] mvebu: GL-MV1000: add custom boot script This allows booting from internal eMMC or SD card just changing the U-Boot mmc_dev variable. In particular, setting mmc_dev to 1 will result in booting from the SD card. Setting the variable to 0 will result in internal eMMC boot (the default). Should the variable be unset or an error condition occur while reading from SD card, internal MMC booting will be tried. Signed-off-by: Enrico Mioso --- target/linux/mvebu/image/cortexa53.mk | 1 + target/linux/mvebu/image/gl-mv1000.bootscript | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 target/linux/mvebu/image/gl-mv1000.bootscript diff --git a/target/linux/mvebu/image/cortexa53.mk b/target/linux/mvebu/image/cortexa53.mk index afe8d9ce21..2a3b5ee11e 100644 --- a/target/linux/mvebu/image/cortexa53.mk +++ b/target/linux/mvebu/image/cortexa53.mk @@ -3,6 +3,7 @@ define Device/glinet_gl-mv1000 DEVICE_VENDOR := GL.iNet DEVICE_MODEL := GL-MV1000 SOC := armada-3720 + BOOT_SCRIPT := gl-mv1000 endef TARGET_DEVICES += glinet_gl-mv1000 diff --git a/target/linux/mvebu/image/gl-mv1000.bootscript b/target/linux/mvebu/image/gl-mv1000.bootscript new file mode 100644 index 0000000000..be93aa36a0 --- /dev/null +++ b/target/linux/mvebu/image/gl-mv1000.bootscript @@ -0,0 +1,28 @@ +# Boot script for GL.iNet GL-MV1000 to make it easier to boot from eMMC or SD +# card. + +setenv bootargs "root=PARTUUID=@ROOT@-02 rw rootwait" + +if test -n "${console}"; then + setenv bootargs "${bootargs} ${console}" +fi + +# Should mmc_dev not be present, default to internal MMC boot +if test -z "${mmc_dev}"; then + setenv mmc_dev 0 +fi + +setenv mmcdev "${mmc_dev}" + +if test -n "${fdt_addr_r}"; then + setenv fdt_addr ${fdt_addr_r} +fi + +if test -n "${kernel_addr_r}"; then + setenv kernel_addr ${kernel_addr_r} +fi + +load mmc ${mmcdev}:1 ${fdt_addr} @DTB@.dtb +load mmc ${mmcdev}:1 ${kernel_addr} Image + +booti ${kernel_addr} - ${fdt_addr} From 2d712021cd776eabe03052dafbb5774c77df9fcf Mon Sep 17 00:00:00 2001 From: Enrico Mioso Date: Tue, 2 Jul 2024 18:09:08 +0200 Subject: [PATCH 10/12] mvebu: enable CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y config option Enable the CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE kernel option to allow for U-Boot environment writing. This might be hiding a problem somewhere else, since the w25q128fw chip supports 32K erases, still this change makes it much easier to switch the GL-MV1000 boot media without an UART cable connection. Thanks to @robimarko and @hacks for the precious hints and suggesting a better approach. Signed-off-by: Enrico Mioso --- target/linux/mvebu/config-6.6 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/mvebu/config-6.6 b/target/linux/mvebu/config-6.6 index 88e5fff4d9..a4572d8a89 100644 --- a/target/linux/mvebu/config-6.6 +++ b/target/linux/mvebu/config-6.6 @@ -270,6 +270,7 @@ CONFIG_MTD_NAND_ECC_SW_HAMMING=y CONFIG_MTD_NAND_MARVELL=y CONFIG_MTD_RAW_NAND=y CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y CONFIG_MTD_SPLIT_FIRMWARE=y CONFIG_MTD_UBI=y CONFIG_MTD_UBI_BEB_LIMIT=20 From 769c933069389099d408edc48ba62fb9b76b4dcd Mon Sep 17 00:00:00 2001 From: Enrico Mioso Date: Tue, 2 Jul 2024 18:09:09 +0200 Subject: [PATCH 11/12] mvebu: GL-MV1000: let u-boot-env be writable again Allows easily changing boot media for GL-MV1000. Signed-off-by: Enrico Mioso --- .../arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts b/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts index 07400fce3a..e098ede75f 100644 --- a/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts +++ b/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts @@ -100,7 +100,6 @@ partition@f0000 { label = "u-boot-env"; reg = <0xf0000 0x8000>; - read-only; }; factory: partition@f8000 { From e5dc16e60d73b672409fc724d4de1b369e515fee Mon Sep 17 00:00:00 2001 From: Qingfang Deng Date: Fri, 28 Jun 2024 16:20:09 +0800 Subject: [PATCH 12/12] kernel: switch crc32 implementation back to default Commit ec885796c05a switched the crc32 implementation from default to byte-at-a-time algorithm, which runs slower but consumes less memory. A decade has passed, and we have already abandoned targets that had small memory, so switch it back to default for faster speed. Signed-off-by: Qingfang Deng --- target/linux/generic/config-5.15 | 4 ++-- target/linux/generic/config-6.1 | 4 ++-- target/linux/generic/config-6.6 | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index cba00711ca..8e2223aebb 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -1043,10 +1043,10 @@ CONFIG_CRAMFS_BLOCKDEV=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_CRC32_BIT is not set -CONFIG_CRC32_SARWATE=y +# CONFIG_CRC32_SARWATE is not set # CONFIG_CRC32_SELFTEST is not set # CONFIG_CRC32_SLICEBY4 is not set -# CONFIG_CRC32_SLICEBY8 is not set +CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC4 is not set # CONFIG_CRC64 is not set # CONFIG_CRC7 is not set diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index 70e87665b7..aa47384137 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -1102,10 +1102,10 @@ CONFIG_CRAMFS_BLOCKDEV=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_CRC32_BIT is not set -CONFIG_CRC32_SARWATE=y +# CONFIG_CRC32_SARWATE is not set # CONFIG_CRC32_SELFTEST is not set # CONFIG_CRC32_SLICEBY4 is not set -# CONFIG_CRC32_SLICEBY8 is not set +CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC4 is not set # CONFIG_CRC64 is not set # CONFIG_CRC64_ROCKSOFT is not set diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index 076a9f9691..e2890e7ffe 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -1004,10 +1004,10 @@ CONFIG_CRAMFS_BLOCKDEV=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_CRC32_BIT is not set -CONFIG_CRC32_SARWATE=y +# CONFIG_CRC32_SARWATE is not set # CONFIG_CRC32_SELFTEST is not set # CONFIG_CRC32_SLICEBY4 is not set -# CONFIG_CRC32_SLICEBY8 is not set +CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC4 is not set # CONFIG_CRC64 is not set # CONFIG_CRC64_ROCKSOFT is not set